JavaFX 列表視圖

2018-03-13 00:04 更新

JavaFX教程 - JavaFX列表視圖


ListView類允許我們顯示一個可滾動的項目列表。

創(chuàng)建列表視圖

以下代碼創(chuàng)建了一個ListView并在之后填充數(shù)據(jù)。

ListView<String> list = new ListView<>();

ObservableList<String> items =FXCollections.observableArrayList (
    "A", "B", "C", "D");
list.setItems(items);

要更改列表視圖控件的大小和高度,使用setPrefHeight和setPrefWidth方法。

list.setPrefWidth(100);
list.setPrefHeight(70);

更改ListView對象的方向

list.setOrientation(Orientation.HORIZONTAL)

SelectionModel和FocusModel跟蹤ListView對象的選擇和焦點。

  • getSelectionModel().getSelectedIndex() - 返回所選的索引
  • getSelectionModel().getSelectedItem() - 返回所選項目
  • getFocusModel().getFocusedIndex() - 返回焦點項的索引
  • getFocusModel().getFocusedItem() - 返回焦點項

默認的selectionMode屬性為SelectionMode.SINGLE。要在默認ListView實例中啟用多選,請使用以下代碼:

listView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

ComboBox單元格

我們可以通過使用CheckBoxListCell,ChoiceBoxListCell,ComboBoxListCell和TextFieldListCell添加各種類型的數(shù)據(jù)。

它就像在Swing中使用CellRenderer。

以下代碼使用ComboBoxListCell類在列表單元格中使用組合框。

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;

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();
  }
}

上面的代碼生成以下結(jié)果。

null

自定義列表視圖

以下代碼顯示了如何將矩形繪制到ListView單元格。

它通過擴展ListCell創(chuàng)建一個自定義單元格。updateItem接收項目參數(shù)中的單元格值。然后它繪制一個紅色的矩形。

  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);
      }
    }
  }

完整的源代碼

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;

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);
      }
    }
  }
}

上面的代碼生成以下結(jié)果。

null

處理列表項目選擇

以下代碼顯示如何處理列表視圖項選擇事件。它注冊用于選擇模型中所選項目屬性的事件處理程序。 新值為從列表視圖中選擇新的值。

    listView.getSelectionModel().selectedItemProperty().addListener(
        (ObservableValue<? extends String> ov, String old_val, 
            String new_val) -> {
                System.out.println(new_val);
                
    });

完整的源代碼

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;

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();
  }
}

上面的代碼生成以下結(jié)果。

null

雙列表視圖

ObservableList是一個集合,能夠在添加,更新和刪除對象時通知UI控件。JavaFX ObservableLists通常用于列表UI控件,如ListView和TableView。

下面的代碼顯示了如何使用ObservableList來處理ListView。它有兩個ListView控件和兩個按鈕。 我們可以使用兩個按鈕將項目從一個列表視圖移動到另一個列表視圖。

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;

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);
  }
}

上面的代碼生成以下結(jié)果。

null

在兩個列表視圖之間拖放

以下代碼顯示如何在自定義對象的兩個列表視圖之間拖放。

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;

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;
  }
}
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號