首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将样式应用于javaFX中的TreeView子节点

将样式应用于javaFX中的TreeView子节点
EN

Stack Overflow用户
提问于 2014-08-14 19:49:44
回答 2查看 11.7K关注 0票数 1

我正在使用JavaFX TreeView,我想实现一个函数,如果我将鼠标悬停在树项目上,该项目及其所有子项目将突出显示。

到目前为止,我成功地使用setCellFactory突出显示了目标项目,如下所示:

代码语言:javascript
运行
复制
treeCell.setOnMouseEntered(new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent mouseEvent) {
        redrawTree()
        treeCell.setStyle("-fx-background-color: #0093ff;");
    }
});

结果是:

但我不知道如何定位并将样式应用到treeCell的子代。此外,这个解决方案需要大量重新绘制树,这对于大树来说是滞后的。

有没有人能帮我向前走,或者给我另一个选择?我认为css解决方案会更好。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-08-14 21:27:46

在外部css文件中,执行以下操作

代码语言:javascript
运行
复制
.tree-cell:hover {
  -fx-background-color: #0093ff ;
}

还要注意(出于中等复杂的原因),如果您使用-fx-background而不是-fx-background-color,文本颜色将对背景颜色的变化做出适当的反应。

要设置子节点(即,作为graphic属性的一部分添加到TreeCell中的节点)的样式,只需执行如下操作

代码语言:javascript
运行
复制
.tree-cell:hover .label {
  /* styles... */
}

这将样式化“悬停”树状单元格内的所有标签。

下面是一个完整的示例:

代码语言:javascript
运行
复制
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TreeTest extends Application {  
    @Override  
    public void start(Stage primaryStage) throws Exception {  
        final StackPane stackPane = new StackPane();  

        TreeItem<Integer> root = createTreeItem(1);

        final TreeView<Integer> tree = new TreeView<>(root);  
        tree.setCellFactory(treeView -> {  
            final Label label = new Label();
            final Label anotherLabel = new Label("Item:");
            label.getStyleClass().add("highlight-on-hover");
            final HBox hbox = new HBox(5, anotherLabel, label);
            TreeCell<Integer> cell =  new TreeCell<Integer>() {  
                @Override  
                protected void updateItem(Integer item, boolean empty) {  
                    super.updateItem(item, empty);  
                    if (empty) {
                        setGraphic(null);
                    } else {
                        setGraphic(hbox);
                    }
                }  
            };  
            cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
            cell.itemProperty().addListener((obs, oldItem, newItem) -> 
                label.setText(newItem != null ? String.valueOf(newItem) : ""));
            return cell ;
        });  
        stackPane.getChildren().add(tree);  
        final Scene scene = new Scene(stackPane);  

        scene.getStylesheets().add(getClass().getResource("tree-hover.css").toExternalForm());

        primaryStage.setScene(scene);  
        primaryStage.setTitle(getClass().getSimpleName());  
        primaryStage.show();  
    }  

    private TreeItem<Integer> createTreeItem(int value) {
        TreeItem<Integer> item = new TreeItem<>(value);
        if (value < 10000) {
            for (int i=0; i<10; i++) {
                item.getChildren().add(createTreeItem(10*value+i));
            }
        }
        return item ;
    }

    public static void main(String[] args) {  
        launch(args);  
    }  
}  

使用tree-hover.css文件:

代码语言:javascript
运行
复制
.tree-cell:hover {
    -fx-background-color: #0093ff ;
}

.tree-cell:hover .highlight-on-hover {
    -fx-text-fill: red ;
}
票数 7
EN

Stack Overflow用户

发布于 2017-10-25 00:00:45

实现这一点的一种解决方案是通过将侦听器设置为行工厂来动态添加和删除已定义的样式类。

因此,setRowFactory方法负责高亮显示子nodes.Basically,它将侦听器附加到每一行的onHover属性中。

当changed事件被触发时,我们必须检查行中是否包含一个展开的、有子节点的节点。如果是这样的话,所有的孩子都将在鼠标上突出显示,并在鼠标移出时突出显示。

代码语言:javascript
运行
复制
private static final String HIGHLIGHT_STYLE = "child-highlight";
private TreeTableView<MyRowContentObject> treeTableView = new TreeTableView<>();
private void setRowFactory() {
    treeTableView.setRowFactory(e -> {
        TreeTableRow<MyRowContentObject> hoverRow = new TreeTableRow<MyRowContentObject>();
        hoverRow.hoverProperty().addListener(new ChangeListener<Boolean>() {
             //you can use a lambda expression for the listener if you want
            @Override
            public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldStatus, Boolean newStatus) {
                List<Node> rows = getRowsList();
                //on mouse hover
                if(newStatus){
                    TreeItem<MyRowContentObject> item = hoverRow.getTreeItem();
                    //validates if there is a node on the hovered row, is expanded and has children
                    if(item != null && item.isExpanded() && item.getChildren().size() > 0) {
                        //row index of the last child of the expanded and hovered node
                        int lastChildIndex = treeTableView.getRow(item.getChildren().get(item.getChildren().size() - 1));
                        //highlights the childs
                        for (int i = hoverRow.getIndex() + 1; i < lastChildIndex + 1; i++)
                            rows.get(i).getStyleClass().add(HIGHLIGHT_STYLE);
                    }
                } else {
                    //on mouse out cleans every single row, because its hard to keep track of the highlighted rows
                    for (Node row : rows)
                        row.getStyleClass().remove(HIGHLIGHT_STYLE);
                }
            }
        });
        return hoverRow;
    });
}

//fetches all rows from the treeTableView
private List<Node> getRowsList(){
    return new ArrayList<>(treeTableView.lookupAll("TreeTableRow"));
}

并将其添加到您的styles.css或您定义的任何其他名称:

代码语言:javascript
运行
复制
.child-highlight {
    -fx-background-color: rgba(255, 11, 44, 0.28);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25307349

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档