我想在TableView中使用自定义控件(代码中的ClientControl)。因此我创建了一个ClientCell类:
public class NewClientCell extends TableCell<Client, Client> {
private final ClientControl cc;
public NewClientCell(ObservableList<Client> suggestions) {
cc = new ClientControl(this.getItem(), suggestions);
this.setAlignment(Pos.CENTER_LEFT);
this.setGraphic(cc);
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
@Override
protected void updateItem(Client c, boolean empty) {
super.updateItem(c, empty);
if(!empty){
setGraphic(cc);
}
}
}
在主程序中,我使用以下代码填写表格:
TableColumn<Client, Client> clmClients = new TableColumn<>("Klient");
clmClients.setCellFactory(new Callback<TableColumn<Client, Client>, TableCell<Client, Client>>() {
@Override
public TableCell<Client, Client> call(TableColumn<Client, Client> p) {
return new NewClientCell(suggestions);
};
});
clmClients.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Client, Client>, ObservableValue<Client>>() {
@Override
public ObservableValue<Client> call(TableColumn.CellDataFeatures<Client, Client> p) {
return new SimpleObjectProperty<Client>(p.getValue());
}
});
getColumns().add(clmClients);
表中的数据来自ObservableList,并且初始化正确。
我现在的问题是自定义控件需要一个Client-Object,它应该从ObservableList中获取,但是“this.getItem()”总是返回null。
如何将客户端对象正确地放入自定义控件?
谢谢!
修改
这是ClientControl的构造函数:
public ClientControl(Client client, ObservableList<Client> suggestions) {
setClient(client);
setSuggestions(suggestions);
FXMLLoader loader = new FXMLLoader(getClass().getResource("ClientControl.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
initTextField();
setLabelText(client.toString());
}
方法setClient是一个简单的setter方法(this.client = client;)。变量客户端和建议就是这么简单的定义:
private ObservableList<Client> suggestions;
private Client client;
答案 0 :(得分:1)
AFAIK,你应该像你一样在构造函数中实例化任何控件,这样它们只会被创建一次(请记住,单元格会被重用于不同的位置)。
但是你需要覆盖一个或多个其他方法,例如updateItem
,以便从当前项目中获取数据。
修改强>
嗯,你正在分配相同的控件,而不是一遍又一遍地改变它。不是在updateItem方法中设置图形,而是设置客户端控件的item属性:
@Override
protected void updateItem(Client c, boolean empty) {
super.updateItem(c, empty);
if(!empty){
cc.setClient(c);
} else {
cc.setClient(null);
}
}
修改2
ClientControl应该将客户端项目作为属性而不是构造函数参数提供,并将其设置在updateItem方法中,而不是在构造函数中。
E.g。这样的事情(未经测试!):
private final ObjectProperty<Client> client = new SimpleObjectProperty<>(this, "client");
public final Client getClient(){
return clientProperty().get();
}
public final void setClient(Client client){
clientProperty().set(client);
}
public ObjectProperty<Client> clientProperty(){
return client;
}
在构造函数中:侦听此属性的更改以设置labelText等。 您还可能希望提供没有客户端参数的构造函数,因为在TableCell构造函数中实例化它时它不可用。
答案 1 :(得分:0)
所以我找到了解决问题的方法。非常感谢Puce的帮助! :-) 现在我通过属性设置客户端:
private ObjectProperty<Client> clientProperty = new SimpleObjectProperty<Client>();
另外,我在ClientControl的构造函数中添加了一个ChangeListener:
public ClientControl(ObservableList<Client> suggestions) {
clientProperty.addListener(new ChangeListener<Client>() {
@Override
public void changed(ObservableValue<? extends Client> observable, Client oldValue,
ClientnewValue) {
if(newValue != null) {
setLabelText(newValue.toString());
}
}
});
setSuggestions(suggestions);
FXMLLoader loader = new FXMLLoader(getClass().getResource("ClientControl.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
initTextField();
}
由于ClientControl中的更改,我的ClientCell类只需要一些简单的更改:
public class NewClientCell extends TableCell<Client, Client> {
private final ClientControl cc;
public NewClientCell(ObservableList<Client> suggestions) {
cc = new ClientControl(suggestions);
this.setAlignment(Pos.CENTER_LEFT);
this.setGraphic(cc);
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
}
@Override
protected void updateItem(Client c, boolean empty) {
super.updateItem(c, empty);
if(!empty){
cc.setClient(c);
}
}
}
在主程序中没有任何改变。
总之,我想再次感谢Puce,我坚持了很多天这个问题......