Перейти к основному содержимому

Отображение пользовательских элементов в JavaFX ListView

· 4 мин. чтения

1. Введение

JavaFX — это мощный инструмент, предназначенный для создания пользовательского интерфейса приложения для различных платформ. Он предоставляет не только компоненты пользовательского интерфейса, но и различные полезные инструменты, такие как свойства и наблюдаемые коллекции.

Компонент ListView удобен для управления коллекциями. А именно, нам не нужно было явно определять DataModel или обновлять элементы ListView . Когда в ObjervableList происходит изменение , оно отражается в виджете ListView .

Однако для такого подхода требуется способ отображения наших пользовательских элементов в JavaFX ListView . В этом руководстве описывается способ настройки внешнего вида объектов домена в ListView .

2. Фабрика клеток

2.1. Поведение по умолчанию

По умолчанию ListView в JavaFX использует метод toString() для отображения объекта.

Таким образом, очевидный подход состоит в том, чтобы переопределить его:

public class Person {
   String firstName;
String lastName;

@Override
public String toString() {
return firstName + " " + lastName;
}
}

Этот подход подходит для обучения и концептуальных примеров. Однако это не лучший способ.

Во-первых, наш класс предметной области берет на себя реализацию дисплея. Таким образом, такой подход противоречит принципу единой ответственности.

Во-вторых, другие подсистемы могут использовать toString() . Например, мы используем метод toString() для регистрации состояния нашего объекта. Для журналов может потребоваться больше полей, чем для элемента ListView . Таким образом, в этом случае одна реализация toString() не может удовлетворить все потребности модуля.

2.2. Cell Factory для отображения пользовательских объектов в ListView

Давайте рассмотрим лучший способ отображения наших пользовательских объектов в JavaFX ListView .

Каждый элемент в ListView отображается с экземпляром класса ListCell . ListCell имеет свойство text . Ячейка отображает свое текстовое значение.

Итак, чтобы настроить текст в экземпляре ListCell , мы должны обновить его свойство text . Где мы можем это сделать? ListCell имеет метод с именем updateItem . Когда появляется ячейка для элемента, он вызывает updateItem . Метод updateItem также запускается при изменении ячейки. Таким образом, мы должны наследовать нашу собственную реализацию от класса ListCell по умолчанию . В этой реализации нам нужно переопределить updateItem .

Но как заставить ListView использовать нашу пользовательскую реализацию вместо стандартной?

ListView может иметь фабрику ячеек. Фабрика ячеек по умолчанию имеет значение null . Мы должны настроить его так, чтобы ListView отображал объекты.

Проиллюстрируем фабрику ячеек на примере:

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 должен реализовать обратный вызов JavaFX. Интерфейс обратного вызова в JavaFX аналогичен стандартному интерфейсу функций Java . Однако JavaFX использует интерфейс обратного вызова по историческим причинам.

Мы должны вызвать реализацию метода updateItem по умолчанию . Эта реализация запускает действия по умолчанию, такие как подключение ячейки к объекту и отображение строки для пустого списка.

Реализация метода updateItem по умолчанию также вызывает setText . Затем он устанавливает текст, который будет отображаться в ячейке.

2.3. Отображение пользовательских элементов в JavaFX ListView с помощью пользовательских виджетов

ListCell предоставляет нам возможность настроить пользовательский виджет в качестве контента. Все, что нам нужно сделать для отображения объектов домена в пользовательских виджетах, — это использовать setGraphics() вместо setCell().

Предположим, нам нужно отобразить каждую строку как 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);
}
}
};
}
}

В этом примере мы устанавливаем для свойства text значение null . Если существуют и текстовые , и графические свойства, текст будет отображаться рядом с виджетом.

Конечно, мы можем настроить логику обратного вызова CheckBox и другие свойства на основе данных нашего пользовательского элемента. Это требует некоторого кодирования, так же, как и настройка текста виджета.

3. Заключение

В этой статье мы рассмотрели способ отображения пользовательских элементов в JavaFX ListView . Мы видели, что ListView позволяет достаточно гибко настроить его. Мы даже можем отображать пользовательские виджеты в наших ячейках ListView.

Как всегда, код примеров доступен на GitHub .