1. Introduction
1.绪论
JavaFX is a powerful tool designed to build application UI for different platforms. It provides not only UI components but different useful tools, such as properties and observable collections.
JavaFX是一个强大的工具,旨在为不同的平台构建应用程序的用户界面。它不仅提供了UI组件,还提供了不同的有用工具,如属性和可观察集合。
ListView component is handy to manage collections. Namely, we didn’t need to define DataModel or update ListView elements explicitly. Once a change happens in the ObjervableList, it reflects in the ListView widget.
ListView组件在管理集合方面很方便。也就是说,我们不需要定义DataModel或明确更新ListView元素。一旦ObjervableList发生变化,它就会反映在ListView部件中。
However, such an approach requires a way to display our custom items in JavaFX ListView. This tutorial describes a way to set up how the domain objects look in the ListView.
然而,这种方法需要在JavaFX ListView中显示我们的自定义项目。本教程描述了一种设置领域对象在ListView中的外观的方法。
2. Cell Factory
2.细胞工厂
2.1. Default Behavior
2.1.默认行为
By default ListView in JavaFX uses the toString() method to display an object.
默认情况下,JavaFX的ListView使用toString()方法来显示一个对象。
So the obvious approach is to override it:
所以明显的做法是覆盖它。
public class Person {
String firstName;
String lastName;
@Override
public String toString() {
return firstName + " " + lastName;
}
}
This approach is ok for the learning and conceptual examples. However, it’s not the best way.
这种方法对于学习和概念性的例子是可以的。然而,这并不是最好的方法。
First, our domain class takes on display implementation. Thus, this approach contradicts to single responsibility principle.
首先,我们的领域类承担了显示实现。因此,这种方法与单一责任原则相抵触。
Second, other subsystems may use toString(). For instance, we use the toString() method to log our object’s state. Logs may require more fields than an item of ListView. So, in this case, a single toString() implementation can’t fulfill every module need.
其次,其他子系统可以使用toString()。例如,我们使用toString()方法来记录我们对象的状态。日志可能需要比ListView的一个项目更多的字段。所以,在这种情况下,单一的toString()实现不能满足每个模块的需要。
2.2. Cell Factory to Display Custom Objects in ListView
2.2.在ListView中显示自定义对象的单元格工厂
Let’s consider a better way to display our custom objects in JavaFX ListView.
让我们考虑一种更好的方式来显示我们在JavaFX ListView中的自定义对象。
Each item in ListView is displayed with an instance of ListCell class. ListCell has a property called text. A cell displays its text value.
ListView中的每个项目都用ListCell类的一个实例显示。ListCell有一个名为text的属性。一个单元格显示其text值。
So to customize the text in the ListCell instance, we should update its text property. Where can we do it? ListCell has a method named updateItem. When the cell for the item appears, it calls the updateItem. The updateItem method also runs when the cell changes. So we should inherit our own implementation from the default ListCell class. In this implementation, we need to override updateItem.
所以为了自定义ListCell实例中的文本,我们应该更新其text属性。我们可以在哪里做呢?ListCell有一个名为updateItem的方法。当项目的单元格出现时,它会调用updateItem。当单元格改变时,updateItem方法也会运行。所以我们应该从默认的ListCell类继承我们自己的实现。在这个实现中,我们需要覆盖updateItem。
But how can we make ListView use our custom implementation instead of the default one?
但是,我们怎样才能使ListView使用我们的自定义实现,而不是默认的实现?
ListView may have a cell factory. Cell factory is null by default. We should set it up to customize the way ListView displays objects.
ListView可以有一个单元格工厂。单元格工厂默认为null。我们应该将其设置为自定义ListView显示对象的方式。
Let’s illustrate cell factory on an example:
让我们用一个例子来说明细胞工厂。
public class PersonCellFactory implements Callback<ListView<Person>, ListCell<Person>> {
@Override
public ListCell<Person> call(ListView<Person> param) {
return new ListCell<>(){
@Override
public void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (empty || person == null) {
setText(null);
} else {
setText(person.getFirstName() + " " + person.getLastName());
}
}
};
}
}
CellFactory should implement a JavaFX callback. The Callback interface in JavaFX is similar to the standard Java Function interface. However, JavaFX uses a Callback interface due to historical reasons.
CellFactory应该实现一个JavaFX回调。JavaFX中的回调接口类似于标准的Java函数接口。然而,由于历史原因,JavaFX使用了Callback接口。
We should call default implementation of the updateItem method. This implementation triggers default actions, such as connecting the cell to the object and showing a row for an empty list.
我们应该调用updateItem方法的默认实现。这个实现会触发默认动作,比如将单元格连接到对象上,并为空列表显示一行。
The default implementation of the method updateItem calls setText, too. It then sets up the text that will be displayed in the cell.
方法updateItem的默认实现也调用setText。然后它设置了将在单元格中显示的文本。
2.3. Display Custom Items in JavaFX ListView With Custom Widgets
2.3.用自定义部件在JavaFX ListView中显示自定义项目
ListCell provides us with an opportunity to set up a custom widget as content. All we should do to display our domain objects in custom widgets is to use setGraphics() instead of setCell().
ListCell为我们提供了一个将自定义widget设置为内容的机会。为了在自定义小组件中显示我们的域对象,我们应该做的就是使用setGraphics()而不是setCell()。
Supposing, we have to display each row as a CheckBox. Let’s take a look at the appropriate cell factory:
假设,我们必须将每一行显示为CheckBox。让我们来看看适当的单元格工厂。
public class CheckboxCellFactory implements Callback<ListView<Person>, ListCell<Person>> {
@Override
public ListCell<Person> call(ListView<Person> param) {
return new ListCell<>(){
@Override
public void updateItem(Person person, boolean empty) {
super.updateItem(person, empty);
if (empty) {
setText(null);
setGraphic(null);
} else if (person != null) {
setText(null);
setGraphic(new CheckBox(person.getFirstName() + " " + person.getLastName()));
} else {
setText("null");
setGraphic(null);
}
}
};
}
}
In this example, we set the text property to null. If both text and graphic properties exist, the text will show beside the widget.
在这个例子中,我们将text属性设置为null。如果text和graphic属性都存在,文本将显示在小组件旁边。
Of course, we can set up the CheckBox callback logic and other properties based on our custom element data. It requires some coding, the same way as setting up the widget text.
当然,我们可以根据我们的自定义元素数据来设置CheckBox的回调逻辑和其他属性。这需要一些编码,与设置小组件文本的方式相同。
3. Conclusion
3.总结
In this article, we considered a way to show custom items in JavaFX ListView. We saw that the ListView allows quite a flexible way to set it up. We can even display custom widgets in our ListView cells.
在这篇文章中,我们考虑了一种在JavaFX ListView中显示自定义项目的方法。我们看到ListView允许相当灵活的方式来设置它。我们甚至可以在我们的ListView单元格中显示自定义小部件。
As always, the code for the examples is available over on GitHub.
像往常一样,这些例子的代码可以在GitHub上找到over。