在JavaFX中覆盖TreeTableCell渲染

时间:2016-06-21 22:11:19

标签: javafx-2

我正在尝试更改TextFieldTreeTableCell的呈现,以将字符串显示为超链接而不是纯文本,但无济于事。好像它应该可以使用setSkin,但类似

setSkin((new HyperLink())。getSkin());

setSkin((new HyperLink(getItem()))。getSkin());

无济于事。有关如何做到这一点的任何见解?

1 个答案:

答案 0 :(得分:1)

你做错了什么

  1. 您没有使用正确的功能来自定义您的单元格:setSkin用于创建自定义控件外观,并且通用于各种控件而不仅仅是单元格,您应该使用单元格工厂。< / LI>
  2. 您没有使用正确的超类:TextFieldTreeTableCell用于创建一个单元格,该单元格包含一个标签,当您单击它时可以将其制作成可编辑的TextField。当您想要“显示不可编辑的,可点击的URL”时,此功能无用。
  3. 方法你应该使用

    细胞具有控制其呈现的特定方法,其在处理细胞时优于皮肤机制。这种特定于细胞的机制称为细胞工厂,并在Cell documentation中记录了一个例子。

    TreeTableColumns允许您在列上set a cell factory来控制列单元格的渲染。在单元格中呈现超链接的相关代码如下:

    emailColumn.setCellFactory(param -> new TreeTableCell<Employee, String>() {
        private Hyperlink link = new Hyperlink();
        {
            setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
        }
    
        @Override
        protected void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
    
            if (item == null || empty) {
                setGraphic(null);
                return;
            }
    
            link.setText(item);
            link.setVisited(getTreeTableRow().getItem().isVisited());
            link.setOnAction(event -> {
                getTreeTableRow().getItem().setVisited(true);
                sendLabel.setText("Send mail to: " + item);
            });
            setGraphic(link);
        }
    });
    

    示例应用

    在下面的屏幕截图中,用户刚刚链接了anna.black@example.com的超链接。

    sample view

    示例代码是Oracle TreeTableView tutorial代码的修改版本。为了跟踪单击TreeTableView中的哪些项目,必须向Employee类添加一个访问属性,以便在更新单元格时适当地设置Hyperlink visited属性。

    import javafx.application.Application;
    import javafx.beans.property.*;
    import javafx.scene.Scene;
    import javafx.scene.control.*;
    import javafx.scene.image.*;
    import javafx.scene.layout.VBox;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    
    import java.util.*;
    
    public class TreeTableViewSample extends Application {
    
        private List<Employee> employees = Arrays.asList(
            new Employee("Ethan Williams", "ethan.williams@example.com"),
            new Employee("Emma Jones", "emma.jones@example.com"),
            new Employee("Michael Brown", "michael.brown@example.com"),
            new Employee("Anna Black", "anna.black@example.com"),
            new Employee("Rodger York", "roger.york@example.com"),
            new Employee("Susan Collins", "susan.collins@example.com"));
    
        private final ImageView depIcon = new ImageView (
                new Image("http://icons.iconarchive.com/icons/custom-icon-design/flatastic-10/16/Bear-icon.png")
        );
    
        final TreeItem<Employee> root = 
            new TreeItem<>(new Employee("Sales Department", ""), depIcon);
        public static void main(String[] args) {
            Application.launch(TreeTableViewSample.class, args);
        }
    
        final Label sendLabel = new Label();
    
        @Override
        public void start(Stage stage) {
            root.setExpanded(true);
            employees.forEach((employee) -> root.getChildren().add(new TreeItem<>(employee)));
            stage.setTitle("Tree Table View Sample");
            final Scene scene = new Scene(new VBox(), 400, 400);
            scene.setFill(Color.LIGHTGRAY);
            VBox sceneRoot = (VBox) scene.getRoot();
    
            TreeTableColumn<Employee, String> empColumn = 
                new TreeTableColumn<>("Employee");
            empColumn.setPrefWidth(150);
            empColumn.setCellValueFactory(
                (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
                new ReadOnlyStringWrapper(param.getValue().getValue().getName())
            );
    
            TreeTableColumn<Employee, String> emailColumn = 
                new TreeTableColumn<>("Email");
            emailColumn.setPrefWidth(190);
            emailColumn.setCellValueFactory(
                (TreeTableColumn.CellDataFeatures<Employee, String> param) -> 
                new ReadOnlyStringWrapper(param.getValue().getValue().getEmail())
            );
            emailColumn.setCellFactory(param -> new TreeTableCell<Employee, String>() {
                private Hyperlink link = new Hyperlink();
                {
                    setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
                }
    
                @Override
                protected void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
    
                    if (item == null || empty) {
                        setGraphic(null);
                        return;
                    }
    
                    link.setText(item);
                    link.setVisited(getTreeTableRow().getItem().isVisited());
                    link.setOnAction(event -> {
                        getTreeTableRow().getItem().setVisited(true);
                        sendLabel.setText("Send mail to: " + item);
                    });
                    setGraphic(link);
                }
            });
    
            TreeTableView<Employee> treeTableView = new TreeTableView<>(root);
            treeTableView.getColumns().setAll(empColumn, emailColumn);
            sceneRoot.getChildren().addAll(treeTableView, sendLabel);
            stage.setScene(scene);
            stage.show();
        }
    
        public class Employee {
            private SimpleStringProperty name;
            private SimpleStringProperty email;
            private SimpleBooleanProperty visited;
    
            public SimpleStringProperty nameProperty() {
                if (name == null) {
                    name = new SimpleStringProperty(this, "name");
                }
                return name;
            }
            public SimpleStringProperty emailProperty() {
                if (email == null) {
                    email = new SimpleStringProperty(this, "email");
                }
                return email;
            }
            private Employee(String name, String email) {
                this.name = new SimpleStringProperty(name);
                this.email = new SimpleStringProperty(email);
                this.visited = new SimpleBooleanProperty(false);
            }
            public String getName() {
                return name.get();
            }
            public void setName(String fName) {
                name.set(fName);
            }
            public String getEmail() {
                return email.get();
            }
            public void setEmail(String fName) {
                email.set(fName);
            }
    
            public void setVisited(boolean visited) {
                this.visited.set(visited);
            }
    
            public boolean isVisited() {
                return visited.get();
            }
        }
    }