gpt4 book ai didi

javafx - 自定义 Javafx 单元工厂弄乱了 setCellValueFactory

转载 作者:行者123 更新时间:2023-12-04 04:38:46 25 4
gpt4 key购买 nike

在与 Netbeans 和 Scenebuilder 混了一段时间之后,我遇到了一个我不太明白的问题。我使用自定义 cellfactory将双击事件绑定(bind)到我的表格 View 中的单元格。但是当我设置 cellfactory 和 cellValueFactory 时,只有自定义 cellFactory 有效果。

我正在尝试使用来自多个对象的数据填充表格 View ,并将双击事件绑定(bind)到第一列的单元格。填充不是问题,我只是使用

idNumber.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("idNumber"));
status.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("status"));

然后我四处搜索以找出如何将双击事件绑定(bind)到表格的单元格并找到 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;
}

我删除了 updatetoString方法只是看看他们是否是我遇到问题的原因。

所以我尝试了
idNumber.setCellFactory(cellFactory);
idNumber.setCellValueFactory(new PropertyValueFactory<LiveStock, String>("idNumber"));

这导致我的单元格为空,但具有双击绑定(bind)

有任何想法吗?

我的 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);
}
}

细胞工厂现在看起来像这样:
    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;
}
};

最佳答案

Cell API 的文档说:

Because by far the most common use case for cells is to show text to a user, this use case is specially optimized for within Cell. This is done by Cell extending from Labeled. This means that subclasses of Cell need only set the text property, rather than create a separate Label and set that within the Cell. ...



当前 source code of Cell constructor将文本设置为空:
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>所以我们定义 TableCell<LiveStock, Integer> .规则的要点:行项目类的属性类型应该匹配 TableColumn 的第二个泛型类型参数,因此也匹配 TableCell 的参数。

getString 方法在您提到的引用答案链接中定义。但这只是用户定义的方法,并非强制使用。

关于javafx - 自定义 Javafx 单元工厂弄乱了 setCellValueFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19245822/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com