The ListView class allows us to display a scrollable list of items.
The following code creates a ListView and fills in data afterwards.
ListView<String> list = new ListView<>(); ObservableList<String> items =FXCollections.observableArrayList ( "A", "B", "C", "D"); list.setItems(items);
To alter the size and height of the list view control, use the setPrefHeight and setPrefWidth methods.
list.setPrefWidth(100); list.setPrefHeight(70);
To change the oriention of a ListView object
list.setOrientation(Orientation.HORIZONTAL)
SelectionModel and FocusModel track the selection and focus of the ListView object.
The default selectionMode property is SelectionMode.SINGLE. To enable multiple selection in a default ListView instance, use the following code:
listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
We can add various types of data by using CheckBoxListCell, ChoiceBoxListCell, ComboBoxListCell, and TextFieldListCell.
It is like using the CellRenderer in Swing.
The following code uses ComboBoxListCell class to use a combo box in the list cell.
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.ListView; import javafx.scene.control.cell.ComboBoxListCell; import javafx.scene.layout.StackPane; import javafx.stage.Stage; /*from www . j a v a 2 s . c o m*/ public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { ObservableList<String> names = FXCollections .observableArrayList(); ObservableList<String> data = FXCollections.observableArrayList(); ListView<String> listView = new ListView<String>(data); listView.setPrefSize(200, 250); listView.setEditable(true); names.addAll("A", "B", "C", "D", "E"); data.add("Double Click to Select Value"); listView.setItems(data); listView.setCellFactory(ComboBoxListCell.forListView(names)); StackPane root = new StackPane(); root.getChildren().add(listView); primaryStage.setScene(new Scene(root, 200, 250)); primaryStage.show(); } }
The code above generates the following result.
The following code shows how to draw rectangle to a ListView cell.
It creates a custom cell by extending the ListCell. The updateItem receives the cell value from item parameter. Then it draws a rectangle with red color.
static class ColorRectCell extends ListCell<String> { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); Rectangle rect = new Rectangle(100, 20); if (item != null) { rect.setFill(Color.RED); setGraphic(rect); } } }
Full source code
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; //from ww w .j a v a 2s .co m public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { ObservableList<String> data = FXCollections.observableArrayList(); ListView<String> listView = new ListView<String>(data); listView.setPrefSize(200, 250); listView.setEditable(true); data.addAll("A", "B", "C", "D", "E"); listView.setItems(data); listView.setCellFactory((ListView<String> l) -> new ColorRectCell()); StackPane root = new StackPane(); root.getChildren().add(listView); primaryStage.setScene(new Scene(root, 200, 250)); primaryStage.show(); } static class ColorRectCell extends ListCell<String> { @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); Rectangle rect = new Rectangle(100, 20); if (item != null) { rect.setFill(Color.RED); setGraphic(rect); } } } }
The code above generates the following result.
The following code shows how to handle list view item selection event. It registers an event handler for selected item property in the selection model. The new value is the new selected value from the list view.
listView.getSelectionModel().selectedItemProperty().addListener(
(ObservableValue<? extends String> ov, String old_val,
String new_val) -> {
System.out.println(new_val);
});
Full source code
import javafx.application.Application; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Scene; import javafx.scene.control.ListView; import javafx.scene.layout.StackPane; import javafx.stage.Stage; //w ww.j a va 2 s . c o m public class Main extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { ObservableList<String> data = FXCollections.observableArrayList(); ListView<String> listView = new ListView<String>(data); listView.setPrefSize(200, 250); data.addAll("A", "B", "C", "D", "E"); listView.setItems(data); listView.getSelectionModel().selectedItemProperty().addListener( (ObservableValue<? extends String> ov, String old_val, String new_val) -> { System.out.println(new_val); }); StackPane root = new StackPane(); root.getChildren().add(listView); primaryStage.setScene(new Scene(root, 200, 250)); primaryStage.show(); } }
The code above generates the following result.
The ObservableList is a collection that is capable of notifying UI controls when objects are added, updated, and removed. JavaFX ObservableLists are typically used in list UI controls such as ListView and TableView.
The following code shows how to use ObservableList to work with ListView. It has two ListView controls and two buttons. We can use the two buttons to move items from one list view to another list view.
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.layout.BorderPane; import javafx.scene.layout.ColumnConstraints; import javafx.scene.layout.GridPane; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.stage.Stage; /*from w w w. j a va 2 s . co m*/ public class Main extends Application { @Override public void start(Stage primaryStage) { BorderPane root = new BorderPane(); Scene scene = new Scene(root, 400, 250, Color.WHITE); GridPane gridpane = new GridPane(); gridpane.setPadding(new Insets(5)); gridpane.setHgap(10); gridpane.setVgap(10); ColumnConstraints column1 = new ColumnConstraints(150, 150, Double.MAX_VALUE); ColumnConstraints column2 = new ColumnConstraints(50); ColumnConstraints column3 = new ColumnConstraints(150, 150, Double.MAX_VALUE); column1.setHgrow(Priority.ALWAYS); column3.setHgrow(Priority.ALWAYS); gridpane.getColumnConstraints().addAll(column1, column2, column3); Label candidatesLbl = new Label("Candidates"); GridPane.setHalignment(candidatesLbl, HPos.CENTER); gridpane.add(candidatesLbl, 0, 0); Label selectedLbl = new Label("selected"); gridpane.add(selectedLbl, 2, 0); GridPane.setHalignment(selectedLbl, HPos.CENTER); // Candidates final ObservableList<String> candidates = FXCollections .observableArrayList("Z", "A", "B", "C", "D"); final ListView<String> candidatesListView = new ListView<>(candidates); gridpane.add(candidatesListView, 0, 1); final ObservableList<String> selected = FXCollections.observableArrayList(); final ListView<String> heroListView = new ListView<>(selected); gridpane.add(heroListView, 2, 1); Button sendRightButton = new Button(" > "); sendRightButton.setOnAction((ActionEvent event) -> { String potential = candidatesListView.getSelectionModel() .getSelectedItem(); if (potential != null) { candidatesListView.getSelectionModel().clearSelection(); candidates.remove(potential); selected.add(potential); } }); Button sendLeftButton = new Button(" < "); sendLeftButton.setOnAction((ActionEvent event) -> { String s = heroListView.getSelectionModel().getSelectedItem(); if (s != null) { heroListView.getSelectionModel().clearSelection(); selected.remove(s); candidates.add(s); } }); VBox vbox = new VBox(5); vbox.getChildren().addAll(sendRightButton, sendLeftButton); gridpane.add(vbox, 1, 1); root.setCenter(gridpane); GridPane.setVgrow(root, Priority.ALWAYS); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
The code above generates the following result.
The following code shows how to drag and drop between two listviews for custom objects.
import javafx.application.Application; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.SelectionMode; import javafx.scene.input.ClipboardContent; import javafx.scene.input.DragEvent; import javafx.scene.input.Dragboard; import javafx.scene.input.MouseEvent; import javafx.scene.input.TransferMode; import javafx.scene.layout.GridPane; import javafx.stage.Stage; import javafx.util.Callback; // w ww . ja v a 2 s. co m public class Main extends Application { private static final ListView<Student> leftListView = new ListView<Student>(); private static final ObservableList<Student> leftList = FXCollections .observableArrayList(); private static final ObservableList<Student> rightList = FXCollections .observableArrayList(); private static final ListView<Student> rightListView = new ListView<Student>(); private static final GridPane rootPane = new GridPane(); public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { initializeComponents(); initializeListeners(); buildGUI(); populateData(); primaryStage.setScene(new Scene(rootPane, 400, 325)); primaryStage.show(); } private void initializeListeners() { // drag from left to right leftListView.setOnDragDetected(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (leftListView.getSelectionModel().getSelectedItem() == null) { return; } Dragboard dragBoard = leftListView.startDragAndDrop(TransferMode.MOVE); ClipboardContent content = new ClipboardContent(); content.putString(leftListView.getSelectionModel().getSelectedItem() .getName()); dragBoard.setContent(content); } }); rightListView.setOnDragOver(new EventHandler<DragEvent>() { @Override public void handle(DragEvent dragEvent) { dragEvent.acceptTransferModes(TransferMode.MOVE); } }); rightListView.setOnDragDropped(new EventHandler<DragEvent>() { @Override public void handle(DragEvent dragEvent) { String player = dragEvent.getDragboard().getString(); rightListView.getItems().addAll(new Student(player)); leftList.remove(new Student(player)); leftListView.setItems(leftList); dragEvent.setDropCompleted(true); } }); // drag from right to left rightListView.setOnDragDetected(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { Dragboard dragBoard = rightListView.startDragAndDrop(TransferMode.MOVE); ClipboardContent content = new ClipboardContent(); content.putString(rightListView.getSelectionModel().getSelectedItem() .getName()); dragBoard.setContent(content); } }); leftListView.setOnDragOver(new EventHandler<DragEvent>() { @Override public void handle(DragEvent dragEvent) { dragEvent.acceptTransferModes(TransferMode.MOVE); } }); leftListView.setOnDragDropped(new EventHandler<DragEvent>() { @Override public void handle(DragEvent dragEvent) { String player = dragEvent.getDragboard().getString(); leftListView.getItems().remove(new Student(player)); rightList.remove(new Student(player)); dragEvent.setDropCompleted(true); } }); } private void buildGUI() { rootPane.setPadding(new Insets(10)); rootPane.setPrefHeight(30); rootPane.setPrefWidth(100); rootPane.setVgap(10); rootPane.setHgap(20); Label playersLabel = new Label("Players"); Label teamLabel = new Label("Team"); rootPane.add(playersLabel, 0, 0); rootPane.add(leftListView, 0, 1); rootPane.add(teamLabel, 1, 0); rootPane.add(rightListView, 1, 1); } private void populateData() { leftList.addAll(new Student("Adam"), new Student("Alex"), new Student( "Alfred")); leftListView.setItems(leftList); rightListView.setItems(rightList); } private void initializeComponents() { initializeListView(leftListView); initializeListView(rightListView); } private void initializeListView(ListView<Student> listView) { listView.setPrefSize(250, 290); listView.setEditable(false); listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); listView.setCellFactory(new StringListCellFactory()); } class StringListCellFactory implements Callback<ListView<Student>, ListCell<Student>> { @Override public ListCell<Student> call(ListView<Student> playerListView) { return new StringListCell(); } class StringListCell extends ListCell<Student> { @Override protected void updateItem(Student player, boolean b) { super.updateItem(player, b); if (player != null) { setText(player.getName()); } } } } } class Student { private String name; public Student(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student player = (Student) o; if (name != null ? !name.equals(player.name) : player.name != null) return false; return true; } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } }