【问题标题】:Stuck with JavaFX ListView卡在 JavaFX 列表视图中
【发布时间】:2025-11-25 05:05:02
【问题描述】:

我正在尝试将基于 Android 的应用程序重写为 JavaFX,但遇到了一个问题。

问题的简要说明如下:

1) 我有根abstract class Field 的类层次结构和FieldCatFieldZebraFieldDog 等子类的数量-这些类中的每一个都有自己独特的足够结构和视觉表示(以 FXML 的形式)

2) ListView 应该显示属于 Field 层次结构的对象列表 - 存储在 ObservableList<Field> listItems

3) 现在我需要将我的每个 FieldWhatever 对象膨胀为 ListView 中的单独行

声明

我无法使用 JavaFX ListView control(?!)

证明

创建ListView 元素的唯一方法是提供CellFactory

public class FieldsListCellFactory<T extends Field> implements Callback<ListView<T>, ListCell<T>> {

    @Override
    public ListCell<T> call(ListView<T> listView) {
         //blah-blah
    }
}

Factory 本身接收单个参数ListView,因此它可以为ListView 的所有元素生成相同的ListCell - 换句话说,我无法根据底层FieldWhatever 对象填充不同的UI 元素。

一开始我都不敢相信——这怎么可能?在 Android 中,我可以根据对象类型/层次结构等夸大任何类型的复杂 UI,但在 JavaFX 中 - 不可能?相信我 - 我花了好几个小时试图修复它 - 没用。

问题

  1. 我是对的吗(我很高兴听到我错了)
  2. 做什么?如何解决情况并放入/放置/充气 完全不同的对象/类/实体的列表/表格列表?

【问题讨论】:

    标签: java swing listview javafx factory


    【解决方案1】:

    广告 1 你错了。

    广告 2 代码如下:

    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.scene.Scene;
    import javafx.scene.control.ListCell;
    import javafx.scene.control.ListView;
    import javafx.stage.Stage;
    
    public class ListViewApp extends Application {
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage stage) throws Exception {
            ListView<Animal> listview = new ListView<>(FXCollections.observableArrayList(new Dog(1, "John"), new Cat(2, "Fluffy")));
            listview.setCellFactory(param -> new ListCell<Animal>() {
    
                @Override
                protected void updateItem(Animal animal, boolean empty) {
                    super.updateItem(animal, empty);
                    if (animal != null) {
                        setText(animal.getText());
                    }
                }
            });
    
            stage.setScene(new Scene(listview));
            stage.show();
        }
    }
    
    class Animal {
        protected final int id;
    
        public Animal(int id) {
            this.id = id;
        }
    
        protected String getText() {
            return "";
        }
    }
    
    class Dog extends Animal {
        private final String owner;
    
        public Dog(int id, String owner) {
            super(id);
            this.owner = owner;
        }
    
        @Override
        protected String getText() {
            return "DOG id=" + id + ", owner=" + owner;
        }
    }
    
    class Cat extends Animal {
        private final String name;
    
        public Cat(int id, String name) {
            super(id);
            this.name = name;
        }
    
        @Override
        protected String getText() {
            return "CAT id=" + id + ", name=" + name;
        }
    }
    

    【讨论】:

    • 我期待有 ListCell&lt;Cat/Dog&gt; 而不是 ListCell... - I was planning to load fxml's in respective constructors not in updateItem()` - 你有解决方案吗?
    • 我真的不明白它应该如何工作?您正在编写有关能够实现所需结构的 Android 代码,您能给我任何指向 Android 代码示例的链接吗?
    • @barmaley 如果我明白你在说什么,那是行不通的。在 JavaFX 中,ListViewTableView 等虚拟化控件在滚动时重用单元格实例。所以做你想做的事情你的ListCell&lt;Dog&gt; 可能会突然有一个Cat 作为它的项目;与ListCell&lt;Cat&gt;Dog 相同。
    • @PrzemekKrysztofiak 例如look here
    • @barmaley 好的,现在我明白了。我的问题是 - 为什么要在 JavaFx 中使用 Android 框架解决方案,Android 解决方案提供的哪些功能是 JavaFx 无法实现的?我真的不明白在构造函数中加载 fxml 的短语,而不是 updateItems()。你按照你正在使用的框架的规则来玩,而不是其他框架的规则。总而言之-我真的看不到问题所在。请提供在 Android 中实现的 JavaFx 无法实现的功能描述。