gpt4 book ai didi

java - ListView - 如何正确配置单元格的显示?

转载 作者:行者123 更新时间:2023-11-30 06:30:49 26 4
gpt4 key购买 nike

我想自定义 ListView 单元格的显示。假设有一个 ListView 包含 Person 类的对象和两个按钮:

  • 添加(生成)新人员
  • 删除选定的人员

我希望实现以下目标:

  1. 未选择单元格时,它必须显示 PersongetBasicView(),这是一个 name 字段。
  2. 当选择一个单元格时,它必须显示一个PersongetExpandedView(),它是一个多行文本name + "/n"+ surname

问题是什么?

我编写的代码满足了上面给出的要求,但出现了其他错误:

  1. 当眨眼间添加一个新的 Person 时,单元格的显示会更改为未实现的 toString() 方法(因此用户会看到 sample.Person@c4f324 类似垃圾)。

Bug no.1

  • 当从最后一个单元格中删除一个Person时,奇怪的事情开始发生。删除的 Person name 保留在向下移动两个单元格的单元格中,因为它不再包含 Person 对象- 无法清除。
  • Bug no.2

    我尝试向单元格的 itemProperty 添加监听器,它可以检查 item 是否为 null,之后我可以将文本设置为 "" 但不幸的是它不起作用。有谁知道如何使我的代码完全发挥作用?

    提供 SSCCE(假设所有文件都在 sample 包中):

    Main.java:

    package sample;

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    import java.io.IOException;

    public class Main extends Application {

    public void start(Stage stage) {
    FXMLLoader fxmlLoader = new FXMLLoader();
    fxmlLoader.setController(Controller.class);
    try {
    Parent parent = FXMLLoader.load(getClass().getResource("/sample/sample.fxml"));
    Scene scene = new Scene(parent);
    stage.setScene(scene);
    stage.show();
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    public static void main(String[] args) {
    launch();
    }
    }

    样本.fxml:

    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.control.Button?>
    <?import javafx.scene.control.ListView?>
    <?import javafx.scene.layout.VBox?>

    <HBox xmlns:fx="http://javafx.com/fxml" fx:controller="sample.Controller">
    <VBox>
    <Button text="Add Person" onAction="#addPerson"/>
    <Button text="Delete Person" onAction="#deletePerson"/>
    </VBox>
    <ListView prefHeight="400" prefWidth="400" fx:id="listView"/>
    </HBox>

    Controller .java:

    package sample;

    import javafx.application.Platform;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.scene.control.ListView;
    import javafx.scene.control.MultipleSelectionModel;
    import javafx.scene.control.cell.TextFieldListCell;
    import java.util.concurrent.ThreadLocalRandom;

    public class Controller {

    @FXML
    private ListView<Person> listView;
    private ObservableList<Person> personList = FXCollections.observableArrayList();
    private String [] names = {"John", "Katherine", "Michael", "August", "Peter"};
    private String [] surnames = {"Jones", "Mayer", "Stevens", "Wayne", "Milton"};

    @FXML
    private void initialize() {
    initializeListCells();
    initializeList();
    }

    private void initializeList() {
    for (int i = 0 ; i < 5 ; i++) {
    personList.add(generatePerson());
    }
    listView.setItems(personList);
    }

    private void initializeListCells() {
    listView.setCellFactory(param -> {
    TextFieldListCell<Person> cell = new TextFieldListCell<Person>();
    cell.selectedProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
    cell.itemProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
    return cell;
    });
    }

    private void handleCellDisplaying(TextFieldListCell<Person> cell) {
    Person person = cell.getItem();
    if (person != null) {
    Platform.runLater(() -> {
    if (!cell.isSelected()) {
    cell.setText(person.getBasicView());
    } else {
    cell.setText(person.getExpandedView());
    }
    });
    } else {
    cell.setText("");
    }
    }

    @FXML
    private void addPerson() {
    personList.add(generatePerson());
    }

    @FXML
    private void deletePerson() {
    MultipleSelectionModel<Person> selectionModel = listView.getSelectionModel();
    if (!selectionModel.isEmpty()) {
    int selectedIndex = selectionModel.getSelectedIndex();
    personList.remove(selectedIndex);
    }
    }

    private Person generatePerson() {
    int nameRandom = ThreadLocalRandom.current().nextInt(1,5);
    int surnameRandom = ThreadLocalRandom.current().nextInt(1,5);
    return new Person(names[nameRandom],surnames[surnameRandom]);
    }
    }

    Person.java:

    package sample;

    public class Person {
    private String name;
    private String surname;

    public Person(String name, String surname) {
    this.name = name;
    this.surname = surname;
    }

    public String getBasicView() {
    return name;
    }

    public String getExpandedView() {
    return name + "\n" + surname;
    }
    }

    最佳答案

    问题在于 TextFieldListCell 实现单元格生命周期方法(updateItem 等)并有效调用 setText(item.toString())在不同的点。这显然会干扰您尝试实现的行为。 (例如,删除最后一个单元格的问题似乎会发生,因为 setText("")TextFieldListCell 将文本重置为之前被调用它以前的值。如果您使用 Platform.runLater(...) hack 使其包围完整的 if-else 子句,那么这个问题就消失了。但是...)

    如果您不需要单元格可编辑,则无需使用 TextFieldListCell:只需使用普通的 ListCell。 (另请注意,处理程序中不需要 Platform.runLater(...) 来更改项目/选定状态。)

    package sample;

    import java.util.concurrent.ThreadLocalRandom;

    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.fxml.FXML;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.scene.control.MultipleSelectionModel;

    public class Controller {

    @FXML
    private ListView<Person> listView;
    private ObservableList<Person> personList = FXCollections.observableArrayList();
    private String[] names = { "John", "Katherine", "Michael", "August", "Peter" };
    private String[] surnames = { "Jones", "Mayer", "Stevens", "Wayne", "Milton" };

    @FXML
    private void initialize() {
    initializeListCells();
    initializeList();
    }

    private void initializeList() {
    for (int i = 0; i < 5; i++) {
    personList.add(generatePerson());
    }
    listView.setItems(personList);
    }

    private void initializeListCells() {
    listView.setCellFactory(param -> {
    ListCell<Person> cell = new ListCell<Person>();
    cell.selectedProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
    cell.itemProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
    return cell;
    });
    }

    private void handleCellDisplaying(ListCell<Person> cell) {
    Person person = cell.getItem();
    if (person != null) {
    if (!cell.isSelected()) {
    cell.setText(person.getBasicView());
    } else {
    cell.setText(person.getExpandedView());
    }
    } else {
    cell.setText("");
    }
    }

    @FXML
    private void addPerson() {
    personList.add(generatePerson());
    }

    @FXML
    private void deletePerson() {
    MultipleSelectionModel<Person> selectionModel = listView.getSelectionModel();
    if (!selectionModel.isEmpty()) {
    int selectedIndex = selectionModel.getSelectedIndex();
    personList.remove(selectedIndex);
    }
    }

    private Person generatePerson() {
    int nameRandom = ThreadLocalRandom.current().nextInt(1, 5);
    int surnameRandom = ThreadLocalRandom.current().nextInt(1, 5);
    return new Person(names[nameRandom], surnames[surnameRandom]);
    }
    }

    关于java - ListView - 如何正确配置单元格的显示?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46174120/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com