I'm trying to get a JFXTreeTableView column to display both text and an image while continuing to use the tree grouping feature.
I modeled my program after the demo and was able to get StringProperty based columns to work correctly, but now attempting to add ObjectProperty<Label>
columns just isn't working. Can anyone give me an example of column using JFXTreeTableView and anything other than a primative or String (i.e. something that uses ObjectProperty<?>
)?
Edit: I just made some progress with this by using an HBox for the column I was able to get my image and text to display.
Below is the code I used to get this far...
In my cell object:
public final class TestObj extends RecursiveTreeObject<TestObj> {
private final ObjectProperty<HBox> source;
public TestObj(String source) {
ImageView iv = new ImageView();
HBox hbox = new HBox();
hbox.setSpacing(10);
VBox vbox = new VBox();
Label l = new Label(source);
vbox.getChildren().add(l);
iv.setFitHeight(20);
iv.setFitWidth(20);
iv.setImage(new Image("/images/test.png"));
l.setGraphic(iv);
hbox.getChildren().addAll(vbox);
this.source = new SimpleObjectProperty<>(hbox);
}
// ... getters & setters
}
In my controller:
public void initialize(URL location, ResourceBundle resources) {
JFXTreeTableColumn<TestObj, HBox> srcColumn = new JFXTreeTableColumn<>("Source");
srcColumn.setPrefWidth(150);
srcColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<TestObj, HBox> x) ->
srcColumn.validateValue(x) ? x.getValue().getValue().sourceProperty() : srcColumn.getComputedValue(x));
//... reset of table setup code
}
Now the problem is the column won't group properly! That is: the image and text could be exactly the same per row, but it won't collapse into a group. Instead, it collapses into many groups with one element each. This makes me think how the table is comparing the cells is the problem... perhaps I need to override a method somewhere?
Edit 2: Now, with the code below, grouping is possible and ungrouped nodes are properly hidden. Additionally, James_D comment was applied to relocate the GUI elements out of the data class. The current problem (outlined in paragraph above) is demonstrated in fig. A and fig. B.
Data object:
public final class TestObj extends RecursiveTreeObject<TestObj> {
//inapplicable vars omitted from this class
//so don't ask why there's just an inner class here ;)
private final ObjectProperty<Register> source;
private final ObjectProperty<Register> destination;
public TestObj(String src, String srcPort, String srcCountry, String dst, String dstPort, String dstCountry) {
this.source = new SimpleObjectProperty<>(new Register(src, srcPort, srcCountry));
this.destination = new SimpleObjectProperty<>(new Register(dst, dstPort, dstCountry));
}
// ... getters & setters
public class Register {
private final String address;
private final String port;
private final String country;
public Register(String address, String port, String country) {
this.address = address;
this.port = port;
this.country = country;
}
//getters ...
}
}
Controller:
public void initialize(URL location, ResourceBundle resources) {
JFXTreeTableColumn<TestObj, TestObj.Register> srcColumn = new JFXTreeTableColumn<>("Source");
srcColumn.setPrefWidth(150); srcColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures<TestObj, TestObj.Register> x) ->
srcColumn.validateValue(x) ? x.getValue().getValue().sourceProperty() : srcColumn.getComputedValue(x));
srcColumn.setCellFactory(new Callback<TreeTableColumn<TestObj, TestObj.Register>, TreeTableCell<TestObj, TestObj.Register>>() {
@Override
public TreeTableCell<TestObj, TestObj.Register> call(TreeTableColumn<TestObj, TestObj.Register> param) {
return new JFXTreeTableCell<TestObj, TestObj.Register>() {
ImageView iv = new ImageView();
@Override
protected void updateItem(TestObj.Register item, boolean empty) {
if(item != null) {
HBox hbox = new HBox();
hbox.setSpacing(10);
VBox vbox = new VBox();
Label l = new Label(item.getAddress() + ":" + item.getPort());
vbox.getChildren().add(l);
iv.setFitHeight(20);
iv.setFitWidth(20);
iv.setImage(new Image("/flags/" + item.getCountry() + ".png"));
l.setGraphic(iv);
hbox.getChildren().addAll(vbox);
setGraphic(hbox);
} else {
setGraphic(null);
}
}
};
}
});
//... above duplicated for dstColumn
//... reset of table setup code
}
Fig. A - Demonstrates the initial view of the table (everything is fine here)
Fig. B - Demonstrates incorrect grouping (there should be 3 groups each with nodes)