1 2 Previous Next 16 Replies Latest reply: Oct 1, 2013 7:34 AM by JGagnon Go to original post RSS
      • 15. Re: List as a table cell
        James_D

        Couldn't resist trying it.

         

        import java.util.ArrayList;
        import java.util.List;
        
        import javafx.beans.property.SimpleListProperty;
        import javafx.beans.property.SimpleStringProperty;
        import javafx.beans.property.StringProperty;
        import javafx.beans.value.ChangeListener;
        import javafx.beans.value.ObservableValue;
        import javafx.collections.FXCollections;
        import javafx.collections.ListChangeListener;
        import javafx.collections.ObservableList;
        import javafx.scene.Node;
        import javafx.scene.control.Label;
        import javafx.scene.control.TableCell;
        import javafx.scene.control.TableColumn;
        import javafx.scene.control.TableColumn.CellDataFeatures;
        import javafx.scene.layout.VBox;
        import javafx.util.Callback;
        
        
        public class ListTableCell<T> extends TableCell<User, ObservableList<T>> {
            private final Callback<T, Node> displayFactory ;
            private final ListChangeListener<Object> changeListener ;
            private final VBox vbox ;
            public ListTableCell(Callback<T, Node> displayFactory) {
                this.displayFactory = displayFactory;
                this.changeListener = new ListChangeListener<Object>() {
                    @Override
                    public void onChanged(Change<? extends Object> change) {
                        rebuildList();
                    }
                };
                this.vbox = new VBox();
                
                itemProperty().addListener(new ChangeListener<ObservableList<T>>() {
                    @Override
                    public void changed(ObservableValue<? extends ObservableList<T>> observable, ObservableList<T> oldList, ObservableList<T> newList) {
                        if (oldList != null) {
                            oldList.removeListener(changeListener);
                        }
                        if (newList != null) {
                            newList.addListener(changeListener);
                        }
                        rebuildList();
                    }
                });
            }
            
            private void rebuildList() {
                ObservableList<T> items = getItem();
                if (items == null) {
                    vbox.getChildren().clear();
                } else {
                    List<Node> nodes = new ArrayList<>();
                    for (T item : items) {
                        nodes.add(displayFactory.call(item));
                    }
                    vbox.getChildren().setAll(nodes);
                }
            }
        }
        

         

        Seems to compile as expected, as does

         

                rolesCol.setCellFactory(new Callback<TableColumn<User, ObservableList<Role>>, TableCell<User, ObservableList<Role>>>() {
        
                    @Override
                    public TableCell<User, ObservableList<Role>> call(TableColumn<User, ObservableList<Role>> col) {
                        return new ListTableCell<Role>(new Callback<Role, Node>() {
                            @Override
                            public Node call(Role role) {
                                return new Label(role.getName());
                            }
                        }) ;
                    }
                    
                });
        

         

        I'll leave it to you to figure out if it actually works, though.

         

        Incidentally, in Java8, the last block of code becomes

        rolesCol.setCellFactory(col -> new ListTableCell<Role>(role -> new Label(role.getName())));
        
        • 16. Re: List as a table cell
          JGagnon

          Initial testing indicates that it works very well.  I made a slight modification:

           

          public class ListTableCell<S, T extends Object> extends TableCell<S, ObservableList<T>> {

          ...

          }

           

          Also, I only specify the 'Object" class in the class definition.  Everywhere else in the class, I just reference 'T'.

           

          Now I only need one generic class instead of 8 nearly identical (but just slightly different) classes.

           

          Thanks very much.

          1 2 Previous Next