Ответ 1
Я понимаю ваш вопрос. Есть в основном два способа установки элементов в Listview
:
1. Создайте ObservableList
и установите элементы Listview
с помощью ObservableList
(listView.setItems(observableList)
).
2. Используйте метод setCellFactory()
класса Listview
.
Вы бы предпочли использовать метод setCellFactory()
, потому что этот подход упрощает процесс, а также помогает отделить бизнес-логику и пользовательский интерфейс (FXML).
Вот более подробное объяснение:
1. Создайте новый файл FXML с именем listview.fxml
, чтобы содержать Listview
, и установите в качестве своего контроллера класс ListViewController
:
Файл: listview.fxml:
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.control.ListView?>
<?import demo.ListViewController?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="CENTER">
<ListView fx:id="listView"/>
</GridPane>
2. Создайте контроллер и назовите его ListViewController
.
Контроллер может загрузить файл listview.fxml
и получить доступ к Listview
.
Файл: ListViewController.java:
package demo;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.util.Callback;
import java.io.IOException;
import java.util.Set;
public class ListViewController
{
@FXML
private ListView listView;
private Set<String> stringSet;
ObservableList observableList = FXCollections.observableArrayList();
public ListViewController()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listview.fxml"));
fxmlLoader.setController(this);
try
{
Parent parent = (Parent)fxmlLoader.load();
Scene scene = new Scene(parent, 400.0 ,500.0);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public void setListView()
{
stringSet.add("String 1");
stringSet.add("String 2");
stringSet.add("String 3");
stringSet.add("String 4");
observableList.setAll(stringSet);
listView.setItems(observableList);
listView.setCellFactory(new Callback<ListView<String>, javafx.scene.control.ListCell<String>>()
{
@Override
public ListCell<String> call(ListView<String> listView)
{
return new ListViewCell();
}
});
}
}
3. Сначала вам нужно установить значение ObservableList
. Это очень важно.
Затем установите элементы списка с помощью ObservableList
и вызовите метод setCellFactory()
на Listview
. В данном примере я просто беру значения String
, добавляя их в набор String
(Set<String> stringSet
).
4. Когда метод setCellFactory()
вызывается в Listview
, он вернет ListCell
. Поэтому для простоты я добавил класс, который расширяет ListCell
, а метод setGraphic()
присутствует для ListCell()
и будет устанавливать элементы ListCell
.
Файл: ListViewCell.java:
package demo;
import javafx.scene.control.ListCell;
public class ListViewCell extends ListCell<String>
{
@Override
public void updateItem(String string, boolean empty)
{
super.updateItem(string,empty);
if(string != null)
{
Data data = new Data();
data.setInfo(string);
setGraphic(data.getBox());
}
}
}
5. Я просто добавил класс, который загрузит listCellItem.fxml
и вернет HBox
, который будет содержать остальные компоненты в качестве дочерних.
Затем HBox
устанавливается на ListCell
.
Файл: listCellItem.fxml:
<?import demo.Data?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Label?>
<HBox xmlns:fx="http://javafx.com/fxml" fx:id="hBox">
<children>
<Label fx:id="label1"/>
<Label fx:id="label2"/>
</children>
</HBox>
Файл: Data.java:
package demo;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import java.io.IOException;
public class Data
{
@FXML
private HBox hBox;
@FXML
private Label label1;
@FXML
private Label label2;
public Data()
{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/listCellItem.fxml"));
fxmlLoader.setController(this);
try
{
fxmlLoader.load();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
public void setInfo(String string)
{
label1.setText(string);
label2.setText(string);
}
public HBox getBox()
{
return hBox;
}
}
Используя этот способ, вы можете использовать метод setCellFactory()
для разделения вещей, которые являются бизнес-логикой и FXML.
Надеюсь, что это будет полезно.