controles - Personalice ListView en JavaFX con FXML
oracle combobox javafx (3)
El ejemplo anterior de @Andvay necesita un par de ajustes para funcionar. Estas son cosas simples para establecer en la pista.
- ListViewController necesita ejecutarse en la cadena de aplicaciones JavaFX.
- Solo puede llamar a los elementos @FXML inyectados desde el método JavaFX initialize ()
- Necesita llamar a setListView ()
- El stringSet en el ejemplo necesita ser asignado con un nuevo antes de llamar a setListView ().
El ListViewController a continuación funciona con estos cambios. Cambié " stringSet " a una lista, " stringList ". El controlador es prácticamente el controlador de muestra proporcionado por Scene Builder 2
public class ListViewController
{
@FXML private ResourceBundle resources;
@FXML private URL location;
@FXML private ListView listView;
private List<String> stringList = new ArrayList<>(5);
private ObservableList observableList = FXCollections.observableArrayList();
public void setListView(){
stringList.add("String 1");
stringList.add("String 2");
stringList.add("String 3");
stringList.add("String 4");
observableList.setAll(stringList);
listView.setItems(observableList);
listView.setCellFactory(
new Callback<ListView<String>, javafx.scene.control.ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> listView) {
return new ListViewCell();
}
});
}
@FXML
void initialize() {
assert listView != null : "fx:id=/"listView/" was not injected: check your FXML file ''CustomList.fxml''.";
setListView();
}
}//ListViewController
La plataforma JavaFX debe iniciarse en el método main () desde una aplicación JavaFX. Netbeans proporciona convenientemente la mayor parte de esta estructura de la plantilla de la aplicación Maven JavaFX.
public class MainApp extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("/fxml/CustomList.fxml"));
Scene scene = new Scene(root);
scene.getStylesheets().add("/styles/Styles.css");
stage.setTitle("CustomList");
stage.setScene(scene);
stage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
*
* @param args the command line arguments
**/
public static void main(String[] args) {
launch(args);
}
}
Quiero hacer una vista de lista personalizada en javafx. Aquí debo unir múltiples componentes en la celda de la lista como sigue, como una etiqueta, un campo de texto, un botón debajo de un HBox y dos botones, un hipervínculo, una etiqueta en otro HBox y estos HBox vienen bajo un VBox y este VBox está bajo el lista individual de la celda y se repetirá y hará una lista Ver.
El código es
<ListView fx:id="ListView" layoutX="0" layoutY="30" prefWidth="600" prefHeight="300">
<HBox fx:id="listBox" alignment="CENTER_LEFT">
<padding><Insets top="5" bottom="5" left="5"></Insets> </padding>
<HBox alignment="CENTER_LEFT" prefWidth="170" minWidth="88">
<Label fx:id="surveyName" text="Field A" styleClass="Name"></Label>
</HBox>
<VBox styleClass="Description" prefWidth="155" minWidth="86">
<HBox>
<HBox styleClass="surveyDesIcon" prefWidth="20" prefHeight="16"></HBox>
<Label fx:id="surveyCode" text="PRW3456HJ"></Label>
</HBox>
<HBox>
<HBox styleClass="DateIcon" prefWidth="20" prefHeight="16"></HBox>
<Label fx:id="Date" text="PRW3456HJ"></Label>
</HBox>
</VBox>
<HBox fx:id="Status" prefWidth="160" minWidth="80">
<Label fx:id="StatusLabel" text="Checking Files.."/>
</HBox>
<HBox fx:id="StatusIcon1" prefWidth="50" prefHeight="50" alignment="CENTER">
<Label styleClass="StatusIcon1" prefWidth="24" prefHeight="24" alignment="CENTER"/>
</HBox>
<HBox fx:id="StatusIcon2" prefWidth="50" prefHeight="50" styleClass="StatusIconBox" alignment="CENTER">
<Hyperlink styleClass="StatusIcon2" prefWidth="24" maxHeight="24" alignment="CENTER"/>
</HBox>
</HBox>
</ListView>
Entiendo tu pregunta Hay principalmente dos formas de establecer elementos en una vista de Listview
:
1. Cree la ObservableList
y establezca los elementos de ListView
con la ObservableList
( listView.setItems(observableList)
).
2. Use el método setCellFactory()
de la clase ListView
.
Preferiría utilizar el método setCellFactory()
, porque este enfoque simplifica el proceso y ayuda a separar la lógica empresarial y la interfaz de usuario (FXML).
Aquí hay una explicación más detallada:
1. Cree un nuevo archivo FXML con el nombre listview.fxml
para contener ListView
y establezca la clase ListViewController
como su controlador:
Archivo: listview.fxml :
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.ListView?>
<?import demo.ListViewController?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<ListView fx:id="listView"/>
</GridPane>
2. Cree el controlador y ListViewController
nombre ListViewController
.
El controlador puede cargar el archivo listview.fxml
y acceder a la vista de lista.
Archivo: ListViewController.java :
package demo;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.util.Callback;
import java.io.IOException;
import java.util.Set;
public class ListViewController
{
@FXML
private ListView listView;
private Set<String> stringSet;
ObservableList observableList = FXCollections.observableArrayList();
public ListViewController()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listview.fxml"));
fxmlLoader.setController(this);
try
{
Parent parent = (Parent)fxmlLoader.load();
Scene scene = new Scene(parent, 400.0 ,500.0);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public void setListView()
{
stringSet.add("String 1");
stringSet.add("String 2");
stringSet.add("String 3");
stringSet.add("String 4");
observableList.setAll(stringSet);
listView.setItems(observableList);
listView.setCellFactory(new Callback<ListView<String>, javafx.scene.control.ListCell<String>>()
{
@Override
public ListCell<String> call(ListView<String> listView)
{
return new ListViewCell();
}
});
}
}
3. Primero necesita establecer el valor de la ObservableList
. Esto es muy importante.
A continuación, establezca los elementos de la lista usando la ObservableList
y llame al método setCellFactory()
en el ListView
. En el ejemplo dado, tomo los valores String
y los agrego al conjunto de String
( Set<String> stringSet
).
4. Cuando se llama al método setCellFactory()
en ListView
, devolverá el ListCell
. Por simplicidad, agregué una clase que extiende el ListCell
, y el método setGraphic()
está presente para el ListCell()
y establecerá los elementos del ListCell
.
Archivo: ListViewCell.java :
package demo;
import javafx.scene.control.ListCell;
public class ListViewCell extends ListCell<String>
{
@Override
public void updateItem(String string, boolean empty)
{
super.updateItem(string,empty);
if(string != null)
{
Data data = new Data();
data.setInfo(string);
setGraphic(data.getBox());
}
}
}
5. Acabo de agregar una clase que cargará el listCellItem.fxml
y devolverá el HBox
, que contendrá los otros componentes como HBox
.
El HBox
se configura en ListCell
.
Archivo: listCellItem.fxml :
<?import demo.Data?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<HBox xmlns:fx="http://javafx.com/fxml" fx:id="hBox">
<children>
<Label fx:id="label1"/>
<Label fx:id="label2"/>
</children>
</HBox>
Archivo: Data.java :
package demo;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import java.io.IOException;
public class Data
{
@FXML
private HBox hBox;
@FXML
private Label label1;
@FXML
private Label label2;
public Data()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listCellItem.fxml"));
fxmlLoader.setController(this);
try
{
fxmlLoader.load();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public void setInfo(String string)
{
label1.setText(string);
label2.setText(string);
}
public HBox getBox()
{
return hBox;
}
}
Utilizando esta forma, puede usar el método setCellFactory()
para separar las cosas que son lógica comercial y FXML.
Espero que esto sea útil.
La respuesta de Anvay por alguna razón no funcionó para mí, lo que tuve que hacer para arreglarla fue solo algunos ajustes muy pequeños:
- eliminar declaración de datos de importación de listCellItem.fxml
- como el comentario debajo de la publicación dice en Data.java pon hBox = fmxlLoader.load ()
También tuve una clase principal (intellij autogenerado).
public class MainMain extends Application { @Override public void start(Stage primaryStage) throws Exception{ FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MainController.fxml")); try { Parent root = fxmlLoader.load(); Scene scene = new Scene(root); primaryStage.setScene(scene); primaryStage.setTitle("Title"); primaryStage.show(); } catch (IOException e) { throw new RuntimeException(e); } } public static void main(String[] args) { launch(args); }
Sé que esto fue probablemente obvio para la mayoría de los expertos aquí, pero estos problemas me dejaron perplejo durante horas mientras estaba depurando.