在搞乱Netbeans和Scenebuilder一段时间后,我遇到了一个我无法理解的问题。我使用自定义cellfactory
将doubleclick事件绑定到tableview中的单元格。但是当我设置cellfactory 和一个cellValueFactory时,只有自定义的cellFactory有效。
我正在尝试使用来自多个对象的数据填充tableview,并将双击事件绑定到第一列的单元格。填充不是问题,我只是使用
idNumber.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("idNumber"));
status.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("status"));
然后我用Google搜索了解如何将doubleclick事件绑定到表格的单元格并找到javafx, TableView: detect a doubleclick on a cell 在其他人中... 我定义了一个像这样的自定义cellFactory:
Callback<TableColumn<LiveStock, String>, TableCell<LiveStock, String>> cellFactory =
new Callback<TableColumn<LiveStock, String>, TableCell<LiveStock, String>>() {
@Override
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<LiveStock, String>() {};
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getClickCount() == 2) {
System.out.println("double clicked!");
TableCell c = (TableCell) event.getSource();
System.out.println("Livestock ID: " + c.getId());
}
}
});
return cell;
}
我删除了update
和toString
方法只是为了查看它们是否是我遇到问题的原因所在。
所以我试过
idNumber.setCellFactory(cellFactory);
idNumber.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("idNumber"));
这会导致我的单元格变空,但双击绑定
任何想法?
我的LiveStock课程如下所示:
package projekt1.fx;
import javafx.beans.property.SimpleStringProperty;
public class LiveStock {
private final int idNumber;
private final SimpleStringProperty ownerID;
private SimpleStringProperty status;
private double lat;
private double longd;
public LiveStock(int idNumber, String ownerID) {
this.idNumber = idNumber;
this.ownerID = new SimpleStringProperty(ownerID);
this.status = new SimpleStringProperty("ok");
}
public int getIdNumber() {
return this.idNumber;
}
// public void setIdNumber(int number) {
// this.idNumber = number;
// }
public String getOwnerID(){
return ownerID.get();
}
public void setOwnerID(String id){
ownerID.set(id);
}
public String getStatus(){
return status.get();
}
public void setStatus(String st){
status.set(st);
}
}
现在,cellfactory看起来像这样:
Callback<TableColumn<LiveStock, String>, TableCell<LiveStock, String>> cellFactory =
new Callback<TableColumn<LiveStock, String>, TableCell<LiveStock, String>>() {
@Override
public TableCell call(TableColumn p) {
TableCell cell = new TableCell<LiveStock, String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
// setText("HELLO WORLD!");
setText(empty ? null : getString());
}
};
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getClickCount() == 2) {
System.out.println("double clicked!");
TableCell c = (TableCell) event.getSource();
System.out.println("Livestock ID: " + c.getId());
togglePopup(null);
}
}
});
return cell;
}
};
答案 0 :(得分:3)
Cell API的文档说:
因为到目前为止,单元格最常见的用例是向a显示文本 用户,此用例专门针对Cell内部进行了优化。这是 由 Labeled 扩展的Cell完成。这意味着子类 单元格只需要设置文本属性,而不是单独创建 在Cell中标记并设置它。 ...
当前source code of Cell constructor将文本设置为null:
public Cell() {
setText(null);
...
}
子类IndexedCell
和子子类TableCell
,它们都没有设置Labeled
的文本。
该文本由源代码中的TableColumn
的默认单元工厂设置。
public static final Callback<TableColumn<?,?>, TableCell<?,?>> DEFAULT_CELL_FACTORY = new Callback<TableColumn<?,?>, TableCell<?,?>>() {
@Override public TableCell<?,?> call(TableColumn<?,?> param) {
return new TableCell() {
@Override protected void updateItem(Object item, boolean empty) {
if (item == getItem()) return;
super.updateItem(item, empty);
if (item == null) {
super.setText(null);
super.setGraphic(null);
} else if (item instanceof Node) {
super.setText(null);
super.setGraphic((Node)item);
} else {
super.setText(item.toString());
super.setGraphic(null);
}
}
};
}
};
但是,通过定义自己的单元工厂来创建新的TableCell
但不在其覆盖的updateItem()
方法中设置文本,将产生一个空(= null)列单元格文本。所以是的,问题的原因是删除updateItem
方法,该方法在内部调用setText(...)
。
修改强>
为TableColumns明确指定泛型类型,
TableColumn<LiveStock, Integer> idNumber = new TableColumn<LiveStock, Integer>("ID No");
这样可以避免类型不匹配或错误的类型铸件 然后,您的用例的单元工厂回调将是
Callback<TableColumn<LiveStock, Integer>, TableCell<LiveStock, Integer>> cellFactory =
new Callback<TableColumn<LiveStock, Integer>, TableCell<LiveStock, Integer>>() {
public TableCell<LiveStock, Integer> call(TableColumn<LiveStock, Integer> p) {
TableCell<LiveStock, Integer> cell = new TableCell<LiveStock, Integer>() {
@Override
public void updateItem(Integer item, boolean empty) {
super.updateItem(item, empty);
setText((item == null || empty) ? null : item.toString());
setGraphic(null);
}
};
cell.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.getClickCount() > 1) {
System.out.println("double clicked!");
TableCell c = (TableCell) event.getSource();
System.out.println("Cell text: " + c.getText());
}
}
});
return cell;
}
};
有什么改变?
LiveStock中idNumber的类型为int
。通过定义new TableColumn<LiveStock, Integer>
我们说这是来自LiveStock行的列,其属性idNumber具有int类型,但泛型类型必须是引用类型,它不能是TableCell<LiveStock, int>
所以我们定义{{1} }}。规则的大拇指:行项类的属性类型应该与TableColumn的第二个泛型类型参数匹配,并且由此也是TableCell的参数。
getString方法在您提到的引用的答案链接中定义。但它只是一个用户定义的方法,不是强制使用它。