2

我正在尝试在 JavaFX ListView 上实现 onMouseEnter 和 onMouseExit 事件。我想要做的是,如果鼠标移动到列表视图的一个节点上,我想更改当前视图中当前可见子节点的背景颜色。

这篇文章有一个很棒的代码示例,但并不是我想要的。 将样式应用于 javaFX 中的 TreeView 子节点

使用该代码作为参考,我正在寻找的是一个给定的树:

根 -> 项目:1 -> 项目:100 -> 项目 1000、项目 1001、项目 1002、项目 1003

当我将鼠标悬停在“项目:100”上时,我希望它和项目 1000* 具有背景颜色变化。

这对我来说似乎很困难,因为 getNextSibling 和 getPreviousSibling 接口位于 TreeItem 上,尽管您可以从 MouseEvent 上的 TreeCell 获取 TreeItem,但您不能(据我所知)更新 TreeItem 上的 CSS 并使其生效一个 TreeCell——因为 setStyle 方法在 TreeCell 上。

关于如何做到这一点的建议?

4

1 回答 1

2

[更新说明:我最初有一个使用TreeItem. 这里提出的解决方案比原来的解决方案要干净得多。]

创建一个ObservableSet<TreeItem<?>>包含TreeItem应突出显示的 s 。然后在单元格工厂中,观察该集合和单元格的treeItemProperty(),并设置样式类(我PseudoClass在下面的示例中使用了 a ),因此如果属于该单元格的树项在集合中,则单元格将突出显示。

最后,向单元格注册mouseEnteredmouseExited处理程序。当鼠标进入单元格时,您可以获得树项目,使用它导航到您需要的任何其他树项目,并将适当的项目添加到您定义的集合中。在mouseExited处理程序中,清除集合(或根据需要执行其他逻辑)。

import java.util.HashSet;

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
import javafx.css.PseudoClass;
import javafx.scene.Scene;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class HighlightingTree extends Application {

    private final PseudoClass highlighted = PseudoClass.getPseudoClass("highlighted");

    @Override
    public void start(Stage primaryStage) {
        TreeView<Integer> tree = new TreeView<>();
        tree.setRoot(buildTreeRoot());

        ObservableSet<TreeItem<Integer>> highlightedItems = FXCollections.observableSet(new HashSet<>());


        tree.setCellFactory(tv -> {

            // the cell:
            TreeCell<Integer> cell = new TreeCell<Integer>() {

                // indicates whether the cell should be highlighted:

                private BooleanBinding highlightCell = Bindings.createBooleanBinding(() -> 
                    getTreeItem() != null && highlightedItems.contains(getTreeItem()), 
                    treeItemProperty(), highlightedItems);

                // listener for the binding above
                // note this has to be scoped to persist alongside the cell, as the binding
                // will use weak listeners, and we need to avoid the listener getting gc'd:
                private ChangeListener<Boolean> listener = (obs, wasHighlighted, isHighlighted) -> 
                    pseudoClassStateChanged(highlighted, isHighlighted);

                // anonymous constructor: register listener with binding    
                {
                    highlightCell.addListener(listener);
                }
            };

            // display correct text:
            cell.itemProperty().addListener((obs, oldItem, newItem) -> {
                if (newItem == null) {
                    cell.setText(null);
                } else {
                    cell.setText(newItem.toString());
                }
            });

            // mouse listeners:
            cell.setOnMouseEntered(e -> {
                if (cell.getTreeItem() != null) {
                    highlightedItems.add(cell.getTreeItem());
                    highlightedItems.addAll(cell.getTreeItem().getChildren());
                }
            });

            cell.setOnMouseExited(e -> highlightedItems.clear());

            return cell ;
        });

        BorderPane uiRoot = new BorderPane(tree);
        Scene scene = new Scene(uiRoot, 600, 600);
        scene.getStylesheets().add("highlight-tree-children.css");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private TreeItem<Integer> buildTreeRoot() {
        return buildTreeItem(1);
    }

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


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

突出显示树children.css:

.tree-cell:highlighted {
    -fx-background: yellow ;
}
于 2014-12-04T16:56:40.340 回答