Dav*_*ins 26 java listview javafx
我对Java,JavaFX和一般的编程有点新意,我有一个问题正在打破我的大脑.
在大多数关于填充ListView的教程中(更具体地说,使用ObservableArrayList),最简单的方法是从字符串的ObservableList中创建它,如下所示:
ObservableList<String> wordsList = FXCollections.observableArrayList("First word","Second word", "Third word", "Etc.");
ListView<String> listViewOfStrings = new ListView<>(wordsList);
Run Code Online (Sandbox Code Playgroud)
但我不想使用字符串.我想使用一个名为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);
Run Code Online (Sandbox Code Playgroud)
每个Word对象只有2个属性:wordString(单词的一个字符串)和definition(另一个字符串,即单词的定义).我两个都有吸气剂和二传手.
您可以看到它的位置 - 代码编译和工作,但是当我在我的应用程序中显示它时,它不会显示ListView中每个单词的标题,而是将Word对象本身显示为字符串!
我的问题是,具体来说,有一种简单的方法可以重写这个:
ListView<Word> listViewOfWords = new ListView<>(wordsList);
Run Code Online (Sandbox Code Playgroud)
这样一来,它不是直接从wordsList中获取Words,而是访问我的observableArrayList的每个Word中的wordString属性?
为了清楚起见,这不适用于android,并且最终将更改,保存和加载单词列表,因此我不能只创建另一个数组来保存wordStrings.我在网上做了一些研究,似乎有一个名为'Cell Factories'的东西,但对于看起来如此简单的问题似乎不必要的复杂,正如我之前所说,我有点编程方面的新手.
有人可以帮忙吗?这是我第一次来这里,所以如果我没有包含足够的代码或者我做错了,我很抱歉.
jew*_*sea 34
解决方法
我建议使用细胞工厂来解决这个问题.
listViewOfWords.setCellFactory(param -> new ListCell<Word>() {
@Override
protected void updateItem(Word item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || item.getWord() == null) {
setText(null);
} else {
setText(item.getWord());
}
}
});
Run Code Online (Sandbox Code Playgroud)
样品申请
import javafx.application.Application;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.stage.Stage;
public class CellFactories extends Application {
@Override
public void start(Stage stage) {
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);
listViewOfWords.setCellFactory(param -> new ListCell<Word>() {
@Override
protected void updateItem(Word item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null || item.getWord() == null) {
setText(null);
} else {
setText(item.getWord());
}
}
});
stage.setScene(new Scene(listViewOfWords));
stage.show();
}
public static class Word {
private final String word;
private final String definition;
public Word(String word, String definition) {
this.word = word;
this.definition = definition;
}
public String getWord() {
return word;
}
public String getDefinition() {
return definition;
}
}
public static void main(String[] args) {
launch(args);
}
}
Run Code Online (Sandbox Code Playgroud)
实施说明
虽然您可以在Word类中覆盖toString以提供针对ListView中的表示的单词的字符串表示,但我建议在ListView中提供单元工厂,以便从单词对象中提取视图数据并在其中表示它列表显示.使用这种方法可以分离关注点,因为您没有将Word对象的图形视图与其文本的toString方法联系起来; 所以toString可以继续有不同的输出(例如Word字段的完整信息,带有单词名称和描述用于调试目的).此外,单元工厂更灵活,因为您可以应用各种图形节点来创建数据的可视化表示,而不仅仅是直接的文本字符串(如果您希望这样做).
另外,另外,我建议通过删除其setter来使Word对象成为不可变对象.如果您确实需要修改单词对象本身,那么处理它的最佳方法是为对象字段提供公开的可观察属性.如果您还希望在对象的可观察属性发生更改时更新UI,那么您需要通过监听对它们的更改来使列表单元格知道相关项目的更改(这在此更加复杂)案件).请注意,包含单词的列表已经是可观察的,ListView将负责处理对该列表的更改,但如果您在显示的单词对象中修改了单词定义,那么您的列表视图将不会获取对该列表的更改. ListView单元工厂中没有适当的侦听器逻辑的定义.
| 归档时间: |
|
| 查看次数: |
24766 次 |
| 最近记录: |