【问题标题】:Multi Pane Mouse Events多窗格鼠标事件
【发布时间】:2023-03-05 01:44:02
【问题描述】:

我们需要有一个“主节点”,当鼠标悬停在其中时,另一个节点(“悬停弹出节点”)会出现在场景中。当鼠标悬停在“主节点”之外时,“悬停弹出节点”就会消失。此外,“主节点”有一个“内部节点”,当点击时,另一个节点(“点击弹出节点”)出现在场景中,如果再次点击,“点击弹出节点”消失。

我们遇到的问题是,当鼠标悬停在“内部节点”内时,“悬停弹出节点”消失了,这是我们不想要的。当鼠标悬停在“主节点”之外时,我们只希望“悬停弹出节点”消失。即当鼠标在“内部节点”内时,我们仍然希望“悬停弹出节点”可见。

查看示例代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class MultiPaneMouseTest extends Application {

    private Rectangle hoverPopupNode;
    private Rectangle clickPopupNode;

    @Override
    public void init() throws Exception {
        super.init();
    }

    @Override
    public void start(Stage primaryStage) {

        BorderPane borderPane = new BorderPane();

        Rectangle mainNode = new Rectangle(200, 100);
        mainNode.setArcWidth(6);
        mainNode.setArcHeight(6);
        mainNode.setFill(Color.web("0x00ff00"));
        mainNode.setOnMouseEntered(e -> {
            System.out.println("mouse entered " + e);
            hoverPopupNode.setVisible(true);
        });
        mainNode.setOnMouseExited(e -> {
            System.out.println("mouse exited " + e);
            hoverPopupNode.setVisible(false);
        });

        Rectangle innerNode = new Rectangle(50, 25);
        innerNode.setArcWidth(6);
        innerNode.setArcHeight(6);
        innerNode.setFill(Color.web("0xffffff"));
        innerNode.setOnMouseClicked(e -> {
            System.out.println("mouse clicked " + e);
            clickPopupNode.setVisible(!clickPopupNode.isVisible());
        });

        hoverPopupNode = new Rectangle(100, 100);
        hoverPopupNode.setArcWidth(6);
        hoverPopupNode.setArcHeight(6);
        hoverPopupNode.setFill(Color.web("0x0000ff"));
        hoverPopupNode.setVisible(false);
        borderPane.setRight(hoverPopupNode);

        clickPopupNode = new Rectangle(100, 100);
        clickPopupNode.setArcWidth(6);
        clickPopupNode.setArcHeight(6);
        clickPopupNode.setFill(Color.web("0xff0000"));
        clickPopupNode.setVisible(false);
        borderPane.setLeft(clickPopupNode);


        StackPane stackPane = new StackPane();
        stackPane.getChildren().add(mainNode);
        stackPane.getChildren().add(innerNode);
        borderPane.setCenter(stackPane);

        Scene scene = new Scene(borderPane);

        primaryStage.setTitle("Sample Test");
        primaryStage.setScene(scene);
        primaryStage.setX(500.0);
        primaryStage.setY(500.0);
        primaryStage.setWidth(500.0);
        primaryStage.setHeight(500.0);
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        super.stop();
    }

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

【问题讨论】:

  • 如果我理解正确,一种可能不是最好的解决方案是将onmouseentered 事件附加到内部节点:在此设置中,如果未设置,则属性@ hoverpopupnode 的 987654323@。
  • @MarcoLuzzara,这在这个示例中可以很好地工作,但在我们的实际应用程序中却不行。在我们的应用程序中,内部节点无法直接访问主节点的关联悬停弹出节点。

标签: javafx javafx-8


【解决方案1】:

mainNode 设为Pane(或合适的子类)并将innerNode 作为子节点添加到其中。如果mainNodechildNode之间存在父子关系,那么鼠标在innerNode上方时仍会认为鼠标悬停在mainNode上。您可以设置Pane(或任何区域)的背景,以实现与Rectangle 相同的填充和圆角半径效果。

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.CornerRadii;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class MultiPaneMouseTest extends Application {

    private Rectangle hoverPopupNode;
    private Rectangle clickPopupNode;

    @Override
    public void init() throws Exception {
        super.init();
    }

    @Override
    public void start(Stage primaryStage) {

        BorderPane borderPane = new BorderPane();

        StackPane mainNode = new StackPane();
        mainNode.setMinSize(200, 100);
        mainNode.setMaxSize(200, 100);

        mainNode.setBackground(new Background(new BackgroundFill(Color.web("0x00ff00"), new CornerRadii(6), Insets.EMPTY)));

        // note you can replace these listeners with
        // hoverPopupNode.visibleProperty().bind(mainNode.hoverProperty());
        // (but obviously after the hoverPopupNode has been instantiated)

        mainNode.setOnMouseEntered(e -> {
            System.out.println("mouse entered " + e);
            hoverPopupNode.setVisible(true);
        });
        mainNode.setOnMouseExited(e -> {
            System.out.println("mouse exited " + e);
            hoverPopupNode.setVisible(false);
        });

        Rectangle innerNode = new Rectangle(50, 25);
        innerNode.setArcWidth(6);
        innerNode.setArcHeight(6);
        innerNode.setFill(Color.web("0xffffff"));
        innerNode.setOnMouseClicked(e -> {
            System.out.println("mouse clicked " + e);
            clickPopupNode.setVisible(!clickPopupNode.isVisible());
        });

        mainNode.getChildren().add(innerNode);

        hoverPopupNode = new Rectangle(100, 100);
        hoverPopupNode.setArcWidth(6);
        hoverPopupNode.setArcHeight(6);
        hoverPopupNode.setFill(Color.web("0x0000ff"));
        hoverPopupNode.setVisible(false);
        borderPane.setRight(hoverPopupNode);

        clickPopupNode = new Rectangle(100, 100);
        clickPopupNode.setArcWidth(6);
        clickPopupNode.setArcHeight(6);
        clickPopupNode.setFill(Color.web("0xff0000"));
        clickPopupNode.setVisible(false);
        borderPane.setLeft(clickPopupNode);


        StackPane stackPane = new StackPane();
        stackPane.getChildren().add(mainNode);

        borderPane.setCenter(stackPane);

        Scene scene = new Scene(borderPane);

        primaryStage.setTitle("Sample Test");
        primaryStage.setScene(scene);
        primaryStage.setX(500.0);
        primaryStage.setY(500.0);
        primaryStage.setWidth(500.0);
        primaryStage.setHeight(500.0);
        primaryStage.show();
    }

    @Override
    public void stop() throws Exception {
        super.stop();
    }

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    相关资源
    最近更新 更多