Java ListView-如何正确配置单元格';什么是显示器?
我想定制Java ListView-如何正确配置单元格';什么是显示器?,java,listview,javafx,javafx-8,Java,Listview,Javafx,Javafx 8,我想定制列表视图单元格的显示。假设有一个ListView包含Person类的对象和两个按钮: 添加(生成)新的人员 要删除选定的人员 我希望实现以下目标: 未选择单元格时,它必须显示人员的getBasicView(),这是一个名称字段 当选择一个单元格时,它必须显示一个人的getExpandedView(),这是一个多行文本name+“/n”+姓氏 问题是什么 我编写的代码满足了上述要求,但出现了其他错误: 当添加一个新的Person进行眨眼操作时,单元格的显示将更改为未实现的toStrin
列表视图
单元格的显示。假设有一个ListView
包含Person
类的对象和两个按钮:
- 添加(生成)新的
人员
- 要删除选定的
人员
人员的getBasicView()
,这是一个名称
字段
人的getExpandedView()
,这是一个多行文本name+“/n”+姓氏
Person
进行眨眼操作时,单元格的显示将更改为未实现的toString()
方法(因此用户会看到示例)。Person@c4f324
类似垃圾)人时,奇怪的事情开始发生。被删除的人员
姓名
仍保留在单元格中,该单元格向下移动了两个单元格,并且由于它不再包含人员
对象,因此无法将其清除itemProperty
,它可以检查item是否为null
,在我可以将文本设置为“
之后,但不幸的是,它不起作用。有人知道如何使我的代码功能齐全吗
提供SSCCE(假设所有文件都在示例
包中):
Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application {
public void start(Stage stage) {
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setController(Controller.class);
try {
Parent parent = FXMLLoader.load(getClass().getResource("/sample/sample.fxml"));
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch();
}
}
sample.fxml:
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.layout.VBox?>
<HBox xmlns:fx="http://javafx.com/fxml" fx:controller="sample.Controller">
<VBox>
<Button text="Add Person" onAction="#addPerson"/>
<Button text="Delete Person" onAction="#deletePerson"/>
</VBox>
<ListView prefHeight="400" prefWidth="400" fx:id="listView"/>
</HBox>
问题在于
TextFieldListCell
实现了单元格生命周期方法(updateItem
等),并在不同点有效地调用setText(item.toString())
。这显然干扰了您试图实现的行为。(例如,删除最后一个单元格的问题似乎是因为在TextFieldListCell
将文本重置为其以前的值之前调用了setText(“”
)hack使其包围了完整的if
-else
子句,然后这个问题就消失了。但是…)
如果不需要编辑单元格,则无需使用TextFieldListCell
:只需使用普通的ListCell
。(还要注意,对于已更改的项目/选定状态,处理程序中不需要平台.runLater(…)
。)
包装样品;
导入java.util.concurrent.ThreadLocalRandom;
导入javafx.collections.FXCollections;
导入javafx.collections.ObservableList;
导入javafx.fxml.fxml;
导入javafx.scene.control.ListCell;
导入javafx.scene.control.ListView;
导入javafx.scene.control.multipleSelectModel;
公共类控制器{
@FXML
私有列表视图列表视图;
私有ObservableList personList=FXCollections.observableArrayList();
私有字符串[]名称={“约翰”、“凯瑟琳”、“迈克尔”、“八月”、“彼得”};
私人字符串[]姓氏={“琼斯”、“迈耶”、“史蒂文斯”、“韦恩”、“米尔顿”};
@FXML
私有void初始化(){
初始化列表单元格();
初始化列表();
}
私有无效初始值列表(){
对于(int i=0;i<5;i++){
添加(generatePerson());
}
setItems(personList);
}
私有void initializeListCells(){
listView.setCellFactory(参数->{
ListCell=新ListCell();
cell.selectedProperty().addListener((可观察、旧值、新值)->handleCellDisplaying(单元格));
cell.itemProperty().addListener((可观察、旧值、新值)->handleCellDisplaying(单元格));
返回单元;
});
}
私有void handlecell显示(列表单元格){
Person=cell.getItem();
if(person!=null){
如果(!cell.isSelected()){
cell.setText(person.getBasicView());
}否则{
cell.setText(person.getExpandedView());
}
}否则{
cell.setText(“”);
}
}
@FXML
个人{
添加(generatePerson());
}
@FXML
私人{
MultipleSelectionModel selectionModel=listView.getSelectionModel();
如果(!selectionModel.isEmpty()){
int-selectedIndex=selectionModel.getSelectedIndex();
personList.remove(selectedIndex);
}
}
私人发电人(){
int nameRandom=ThreadLocalRandom.current().nextInt(1,5);
int-namesrandom=ThreadLocalRandom.current().nextInt(1,5);
返回新的人员(姓名[姓名随机]、姓氏[姓氏随机]);
}
}
我假设1。在您的问题中,应改为“未选择单元格时”。你想让这些单元格可以编辑吗?@James_D Nope,只是显示而已。是的,未选中-我的不好。那么为什么要使用TextFieldListCell
?这已经在其整个生命周期中调用了setText(item.toString())
,这显然干扰了您正在定义的功能。只需使用一个普通的ListCell
。你说你不能复制第二个bug?只需选择最后一项,然后继续单击“删除人员”按钮。@notmyf4ulty是的,刚刚解决。我现在可以复制了。如果在整个if
-else
中使用Platform.runLater(…)
,实际上可以消除这种情况,但是没有理由使用TextFieldListCell
,如果只使用ListCell
(它从不调用setText()
),则不需要Platform.runLater()
。这个例子是一个更复杂的案例(原始的列表视图
package sample; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.ListView; import javafx.scene.control.MultipleSelectionModel; import javafx.scene.control.cell.TextFieldListCell; import java.util.concurrent.ThreadLocalRandom; public class Controller { @FXML private ListView<Person> listView; private ObservableList<Person> personList = FXCollections.observableArrayList(); private String [] names = {"John", "Katherine", "Michael", "August", "Peter"}; private String [] surnames = {"Jones", "Mayer", "Stevens", "Wayne", "Milton"}; @FXML private void initialize() { initializeListCells(); initializeList(); } private void initializeList() { for (int i = 0 ; i < 5 ; i++) { personList.add(generatePerson()); } listView.setItems(personList); } private void initializeListCells() { listView.setCellFactory(param -> { TextFieldListCell<Person> cell = new TextFieldListCell<Person>(); cell.selectedProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell)); cell.itemProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell)); return cell; }); } private void handleCellDisplaying(TextFieldListCell<Person> cell) { Person person = cell.getItem(); if (person != null) { Platform.runLater(() -> { if (!cell.isSelected()) { cell.setText(person.getBasicView()); } else { cell.setText(person.getExpandedView()); } }); } else { cell.setText(""); } } @FXML private void addPerson() { personList.add(generatePerson()); } @FXML private void deletePerson() { MultipleSelectionModel<Person> selectionModel = listView.getSelectionModel(); if (!selectionModel.isEmpty()) { int selectedIndex = selectionModel.getSelectedIndex(); personList.remove(selectedIndex); } } private Person generatePerson() { int nameRandom = ThreadLocalRandom.current().nextInt(1,5); int surnameRandom = ThreadLocalRandom.current().nextInt(1,5); return new Person(names[nameRandom],surnames[surnameRandom]); } }
package sample;
public class Person {
private String name;
private String surname;
public Person(String name, String surname) {
this.name = name;
this.surname = surname;
}
public String getBasicView() {
return name;
}
public String getExpandedView() {
return name + "\n" + surname;
}
}
package sample;
import java.util.concurrent.ThreadLocalRandom;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.MultipleSelectionModel;
public class Controller {
@FXML
private ListView<Person> listView;
private ObservableList<Person> personList = FXCollections.observableArrayList();
private String[] names = { "John", "Katherine", "Michael", "August", "Peter" };
private String[] surnames = { "Jones", "Mayer", "Stevens", "Wayne", "Milton" };
@FXML
private void initialize() {
initializeListCells();
initializeList();
}
private void initializeList() {
for (int i = 0; i < 5; i++) {
personList.add(generatePerson());
}
listView.setItems(personList);
}
private void initializeListCells() {
listView.setCellFactory(param -> {
ListCell<Person> cell = new ListCell<Person>();
cell.selectedProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
cell.itemProperty().addListener((observable, oldValue, newValue) -> handleCellDisplaying(cell));
return cell;
});
}
private void handleCellDisplaying(ListCell<Person> cell) {
Person person = cell.getItem();
if (person != null) {
if (!cell.isSelected()) {
cell.setText(person.getBasicView());
} else {
cell.setText(person.getExpandedView());
}
} else {
cell.setText("");
}
}
@FXML
private void addPerson() {
personList.add(generatePerson());
}
@FXML
private void deletePerson() {
MultipleSelectionModel<Person> selectionModel = listView.getSelectionModel();
if (!selectionModel.isEmpty()) {
int selectedIndex = selectionModel.getSelectedIndex();
personList.remove(selectedIndex);
}
}
private Person generatePerson() {
int nameRandom = ThreadLocalRandom.current().nextInt(1, 5);
int surnameRandom = ThreadLocalRandom.current().nextInt(1, 5);
return new Person(names[nameRandom], surnames[surnameRandom]);
}
}