title: (JFoenix) JFXTreeTableView how to display/group image + string in column?
body: <p>I'm trying to get a JFXTreeTableView column to display both text and an image while continuing to use the tree grouping feature. </p>
  
  <p>I modeled my program after the demo and was able to get StringProperty based columns to work correctly, but now attempting to add <code>ObjectProperty&lt;Label&gt;</code> 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 <code>ObjectProperty&lt;?&gt;</code>)?</p>
  
  <p><strong>Edit:</strong> 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.</p>
  
  <p>Below is the code I used to get this far...</p>
  
  <p><strong>In my cell object:</strong></p>
  
  <pre><code>public final class TestObj extends RecursiveTreeObject&lt;TestObj&gt; {
          private final ObjectProperty&lt;HBox&gt; 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&lt;&gt;(hbox);
          }
  
          // ... getters &amp; setters
  }
  </code></pre>
  
  <p><strong>In my controller:</strong></p>
  
  <pre><code>public void initialize(URL location, ResourceBundle resources) {
          JFXTreeTableColumn&lt;TestObj, HBox&gt; srcColumn = new JFXTreeTableColumn&lt;&gt;("Source");
          srcColumn.setPrefWidth(150);
          srcColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures&lt;TestObj, HBox&gt; x) -&gt;
          srcColumn.validateValue(x) ? x.getValue().getValue().sourceProperty() : srcColumn.getComputedValue(x));
  
          //... reset of table setup code
  }
  </code></pre>
  
  <p>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?</p>
  
  <p><strong>Edit 2:</strong> 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.</p>
  
  <p><strong>Data object:</strong></p>
  
  <pre><code>public final class TestObj extends RecursiveTreeObject&lt;TestObj&gt; {
          //inapplicable vars omitted from this class
          //so don't ask why there's just an inner class here ;)
          private final ObjectProperty&lt;Register&gt; source;
          private final ObjectProperty&lt;Register&gt; destination;
  
          public TestObj(String src, String srcPort, String srcCountry, String dst, String dstPort, String dstCountry) {
                  this.source = new SimpleObjectProperty&lt;&gt;(new Register(src, srcPort, srcCountry));
                  this.destination = new SimpleObjectProperty&lt;&gt;(new Register(dst, dstPort, dstCountry));
          }
  
          // ... getters &amp; 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 ...
           }
  }
  </code></pre>
  
  <p><strong>Controller:</strong></p>
  
  <pre><code>public void initialize(URL location, ResourceBundle resources) {
          JFXTreeTableColumn&lt;TestObj, TestObj.Register&gt; srcColumn = new JFXTreeTableColumn&lt;&gt;("Source");
          srcColumn.setPrefWidth(150); srcColumn.setCellValueFactory((TreeTableColumn.CellDataFeatures&lt;TestObj, TestObj.Register&gt; x) -&gt;
              srcColumn.validateValue(x) ? x.getValue().getValue().sourceProperty() : srcColumn.getComputedValue(x));
      srcColumn.setCellFactory(new Callback&lt;TreeTableColumn&lt;TestObj, TestObj.Register&gt;, TreeTableCell&lt;TestObj, TestObj.Register&gt;&gt;() {
          @Override
          public TreeTableCell&lt;TestObj, TestObj.Register&gt; call(TreeTableColumn&lt;TestObj, TestObj.Register&gt; param) {
              return new JFXTreeTableCell&lt;TestObj, TestObj.Register&gt;() {
                  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
  }
  </code></pre>
  
  <p><strong>Fig. A</strong> - Demonstrates the initial view of the table (everything is fine here)</p>
  
  <p><a href="https://i.stack.imgur.com/HWdka.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/HWdka.png" alt="Demonstrates the initial view of the table (everything is fine here)"></a></p>
  
  <p><strong>Fig. B</strong> - Demonstrates incorrect grouping (there should be 3 groups each with nodes)</p>
  
  <p><a href="https://i.stack.imgur.com/B3CMm.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/B3CMm.png" alt="Demonstrates incorrect grouping (there should be 3 groups each with nodes)"></a></p>