Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javaFX上的特定行上应用css_Javafx - Fatal编程技术网

在javaFX上的特定行上应用css

在javaFX上的特定行上应用css,javafx,Javafx,我在项目中使用了TreeTableView,当用户选择一行时,我想做一些特定的事情: 我希望这一行有一个不同的背景颜色,但我也希望它的孩子和家长也有这种颜色 我找到了访问每一行和子行的方法,但我不知道如何指定这个背景色。我尝试使用我的customs TreeTableCells并在updateItem方法中添加样式来完成此操作,但每次选择一个项目时都不会调用此方法 因此,我想尝试在我的treetableview中添加listener,这似乎是一个更好的主意,但事实上,我无法访问行以提供任何样式。

我在项目中使用了TreeTableView,当用户选择一行时,我想做一些特定的事情:

我希望这一行有一个不同的背景颜色,但我也希望它的孩子和家长也有这种颜色

我找到了访问每一行和子行的方法,但我不知道如何指定这个背景色。我尝试使用我的customs TreeTableCells并在updateItem方法中添加样式来完成此操作,但每次选择一个项目时都不会调用此方法


因此,我想尝试在我的treetableview中添加listener,这似乎是一个更好的主意,但事实上,我无法访问行以提供任何样式。

这里的基本策略是:

  • 为要突出显示的条件创建(在下面的示例中,我为“选定的子项”创建了一个,为“选定的父项”创建了一个)
  • 使用创建表的行。行应该在
    updateItem
    方法中更新其伪类状态,并且如果所选项目发生更改,也应该更新其
    pseudoclass
    状态。您可以在表的选定项上放置一个侦听器来执行第二个操作
  • 使用您在第一步中定义的伪类,在外部CSS文件中添加CSS,以您想要的方式设置行的样式
  • 以下是SSCCE:

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Random;
    import java.util.function.Function;
    
    import javafx.application.Application;
    import javafx.beans.property.IntegerProperty;
    import javafx.beans.property.SimpleIntegerProperty;
    import javafx.beans.property.SimpleStringProperty;
    import javafx.beans.property.StringProperty;
    import javafx.beans.value.ObservableValue;
    import javafx.collections.ListChangeListener.Change;
    import javafx.css.PseudoClass;
    import javafx.scene.Scene;
    import javafx.scene.control.TreeItem;
    import javafx.scene.control.TreeTableColumn;
    import javafx.scene.control.TreeTableRow;
    import javafx.scene.control.TreeTableView;
    import javafx.stage.Stage;
    
    public class TreeTableViewHighlightSelectedPath extends Application {
    
        private PseudoClass childOfSelected = PseudoClass.getPseudoClass("child-of-selected");
        private PseudoClass parentOfSelected = PseudoClass.getPseudoClass("parent-of-selected");
    
        @Override
        public void start(Stage primaryStage) {
            TreeTableView<Item> table = new TreeTableView<>(createRandomTree(50));
    
            table.setRowFactory(ttv -> {
                TreeTableRow<Item> row = new TreeTableRow<Item>() {
                    @Override
                    protected void updateItem(Item item, boolean empty) {
                        super.updateItem(item, empty);
                        if (empty) {
                            pseudoClassStateChanged(parentOfSelected, false);
                            pseudoClassStateChanged(childOfSelected, false);
                        } else {
                            updateState(this);
                        }
                    }
                };
    
                table.getSelectionModel().getSelectedItems().addListener(
                        (Change<? extends TreeItem<Item>> c) -> updateState(row));
    
                return row ;
            });
    
            table.getColumns().add(column("Item", Item::nameProperty));
            table.getColumns().add(column("Value", Item::valueProperty));
    
            Scene scene = new Scene(table, 800, 800);
            scene.getStylesheets().add("table-row-highlight.css");
            primaryStage.setScene(scene);
            primaryStage.show();
    
        }
    
        private <T> void updateState(TreeTableRow<T> row) {
            TreeTableView<T> table = row.getTreeTableView() ;
            TreeItem<T> item = row.getTreeItem();
    
            // if item is selected, just use default "selected" highlight,
            // and set "child-of-selected" and "parent-of-selected" to false:
            if (item == null || table.getSelectionModel().getSelectedItems().contains(item)) {
                row.pseudoClassStateChanged(childOfSelected, false);
                row.pseudoClassStateChanged(parentOfSelected, false);
                return ;
            }
    
            // check to see if item is parent of any selected item:
            for (TreeItem<T> selectedItem : table.getSelectionModel().getSelectedItems()) {
                for (TreeItem<T> parent = selectedItem.getParent(); parent != null ; parent = parent.getParent()) {
                    if (parent == item) {
                        row.pseudoClassStateChanged(parentOfSelected, true);
                        row.pseudoClassStateChanged(childOfSelected, false);
                        return ;
                    }
                }
            }
    
            // check to see if item is child of any selected item:
            for (TreeItem<T> ancestor = item.getParent() ; ancestor != null ; ancestor = ancestor.getParent()) {
                if (table.getSelectionModel().getSelectedItems().contains(ancestor)) {
                    row.pseudoClassStateChanged(childOfSelected, true);
                    row.pseudoClassStateChanged(parentOfSelected, false);
                    return ;
                }
            }
    
            // if we got this far, clear both pseudoclasses:
    
            row.pseudoClassStateChanged(childOfSelected, false);
            row.pseudoClassStateChanged(parentOfSelected, false);
    
        }
    
        private <S,T> TreeTableColumn<S,T> column(String title, Function<S, ObservableValue<T>> property) {
            TreeTableColumn<S,T> column = new TreeTableColumn<>(title);
            column.setCellValueFactory(cellData -> property.apply(cellData.getValue().getValue()));
            return column ;
        }
    
        private TreeItem<Item> createRandomTree(int numNodes) {
            Random rng = new Random();
            TreeItem<Item> root = new TreeItem<>(new Item("Item 1", rng.nextInt(1000)));
            root.setExpanded(true);
            List<TreeItem<Item>> items = new ArrayList<>();
            items.add(root);
    
            for (int i = 2 ; i <= numNodes; i++) {
                Item item = new Item("Item "+i, rng.nextInt(1000));
                TreeItem<Item> treeItem = new TreeItem<>(item);
                treeItem.setExpanded(true);
                items.get(rng.nextInt(items.size())).getChildren().add(treeItem);
                items.add(treeItem);
            }
    
            return root ;
        }
    
        public static class Item {
            private StringProperty name = new SimpleStringProperty();
            private IntegerProperty value = new SimpleIntegerProperty();
    
            public Item(String name, int value) {
                setName(name);
                setValue(value);
            }
    
            public final StringProperty nameProperty() {
                return this.name;
            }
    
    
            public final java.lang.String getName() {
                return this.nameProperty().get();
            }
    
    
            public final void setName(final java.lang.String name) {
                this.nameProperty().set(name);
            }
    
    
            public final IntegerProperty valueProperty() {
                return this.value;
            }
    
    
            public final int getValue() {
                return this.valueProperty().get();
            }
    
    
            public final void setValue(final int value) {
                this.valueProperty().set(value);
            }
    
            @Override
            public String toString() {
                return String.format("%s (%d)", getName(), getValue());
            }
    
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    
    这将提供以下信息:


    此版本将高亮显示树中选定项的所有子节点和所有祖先节点。如果只想突出显示直接的子行和父行,可以简化
    updateState()
    方法。

    这基本上与以下内容相同:您只需要调整树表视图的解决方案。非常感谢,我将为我的代码调整它!这正是我想做的事@不客气。如果回答了您的问题,请将答案标记为正确;如果其他人有类似的问题,这将使他们更容易找到它。我试过了,但我只是不知道如何标记它。。。“我只是将它重命名为已解决吗?”WilliamEstupina单击答案旁边的复选标记。多亏了你,我才能够使它工作。但只剩下一个问题:它在选择更改时与侦听器配合得很好,但当我展开表然后取消展开时遇到了问题。一些空行被涂上了颜色。但是,当我再次选择另一项时,这会停止错误。因此,我想在进行或取消ax扩展时触发updateState函数。他们有没有简单的方法让一个侦听器加入到TreeTableView的扩展中?