如何使用自定义对象在JavaFX中填充ListView?

我对Java,JavaFX和一般编程还是有点陌生,但是我遇到了一个困扰我的问题。


在大多数教程中,我查找了有关填充ListView(更具体地说,使用ObservableArrayList)的方法,最简单的方法是从字符串的ObservableList中进行填充,如下所示:


ObservableList<String> wordsList = FXCollections.observableArrayList("First word","Second word", "Third word", "Etc."); 

ListView<String> listViewOfStrings = new ListView<>(wordsList);

但是我不想使用字符串。我想使用我制作的名为Words的自定义对象:


ObservableList<Word> wordsList = FXCollections.observableArrayList();

wordsList.add(new Word("First Word", "Definition of First Word");

wordsList.add(new Word("Second Word", "Definition of Second Word");

wordsList.add(new Word("Third Word", "Definition of Third Word");

ListView<Word> listViewOfWords = new ListView<>(wordsList);

每个Word对象只有两个属性:wordString(单词的字符串)和definition(另一个字符串,它是单词的定义)。我既有getter也有setter。


您可以看到代码的编译和工作原理,但是当我在应用程序中显示它时,而不是在ListView中显示每个单词的标题时,它会将Word对象本身显示为字符串!


该图显示了我的应用程序及其ListView


我的问题是,具体来说,是否有一种简单的方法可以重写:


ListView<Word> listViewOfWords = new ListView<>(wordsList);

以这种方式,而不是直接从wordsList中获取Words,它访问我的observableArrayList的每个Word中的wordString属性?


请注意,这不适用于android,单词列表最终将被更改,保存和加载,因此我不能仅仅制作另一个数组来保存wordStrings。我已经在网络上做了一些研究,似乎有一个叫做“细胞工厂”的东西,但是看起来如此简单的问题似乎不必要地复杂,正如我之前所说,我有点编程方面的新手。


有人可以帮忙吗?这是我第一次来,所以如果我没有包含足够的代码或者做错了什么,我感到抱歉。


函数式编程
浏览 1007回答 3
3回答

哆啦的时光机

我建议使用电池工厂来解决此问题。listViewOfWords.setCellFactory(param -> new ListCell<Word>() {&nbsp; &nbsp; @Override&nbsp; &nbsp; protected void updateItem(Word item, boolean empty) {&nbsp; &nbsp; &nbsp; &nbsp; super.updateItem(item, empty);&nbsp; &nbsp; &nbsp; &nbsp; if (empty || item == null || item.getWord() == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setText(null);&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setText(item.getWord());&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }});样品申请添加图片import javafx.application.Application;import javafx.collections.*;import javafx.scene.Scene;import javafx.scene.control.*;import javafx.stage.Stage;public class CellFactories extends Application {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; @Override&nbsp; &nbsp; public void start(Stage stage) {&nbsp; &nbsp; &nbsp; &nbsp; ObservableList<Word> wordsList = FXCollections.observableArrayList();&nbsp; &nbsp; &nbsp; &nbsp; wordsList.add(new Word("First Word", "Definition of First Word"));&nbsp; &nbsp; &nbsp; &nbsp; wordsList.add(new Word("Second Word", "Definition of Second Word"));&nbsp; &nbsp; &nbsp; &nbsp; wordsList.add(new Word("Third Word", "Definition of Third Word"));&nbsp; &nbsp; &nbsp; &nbsp; ListView<Word> listViewOfWords = new ListView<>(wordsList);&nbsp; &nbsp; &nbsp; &nbsp; listViewOfWords.setCellFactory(param -> new ListCell<Word>() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; protected void updateItem(Word item, boolean empty) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.updateItem(item, empty);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (empty || item == null || item.getWord() == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setText(null);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setText(item.getWord());&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; stage.setScene(new Scene(listViewOfWords));&nbsp; &nbsp; &nbsp; &nbsp; stage.show();&nbsp; &nbsp; }&nbsp; &nbsp; public static class Word {&nbsp; &nbsp; &nbsp; &nbsp; private final String word;&nbsp; &nbsp; &nbsp; &nbsp; private final String definition;&nbsp; &nbsp; &nbsp; &nbsp; public Word(String word, String definition) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.word = word;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.definition = definition;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public String getWord() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return word;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public String getDefinition() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return definition;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public static void main(String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; launch(args);&nbsp; &nbsp; }}实施说明尽管您可以在Word类中重写toString来提供该单词的字符串表示形式,以供ListView中的表示形式使用,但我还是建议在ListView中提供一个单元工厂,以从单词对象中提取视图数据并在您的视图中进行表示列表显示。使用这种方法,因为您没有将Word对象的图形视图与其文本toString方法联系在一起,所以可以将关注点分离。因此toString可以继续具有不同的输出(例如,有关Word字段的完整信息,其中包含单词名称和用于调试目的的描述)。此外,单元工厂更加灵活,因为您可以应用各种图形节点来创建数据的可视表示,而不仅仅是纯文本字符串(如果您愿意这样做)。另外,我建议您将Word对象设为不可变的对象,删除他们的二传手。如果您确实需要修改单词对象本身,那么处理该对象的最佳方法是公开对象字段的可观察属性。如果您还希望UI随着对象的可观察属性的变化而更新,那么您需要通过侦听对它们的更改,使列表单元知道对关联项目的更改(这在此方面要复杂得多)案件)。请注意,包含单词的列表已经可以观察到,并且ListView将负责处理对该列表的更改,但是如果您在显示的单词对象中修改了实例的单词定义,则您的列表视图将不会接受对单词的更改。 ListView单元工厂中没有适当的侦听器逻辑的情况下定义。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java