JavaFX 点击穿透叠加 StackPane

14

示意图

如上图所示,我有一个StackPane包含两个元素,一个BorderPane(其中又包含了一个Canvas和一个StatusBar)和另一个StackPane(其中包含一些其他的UI元素)。

我希望能够点击绿色StackPane中不可见区域的部分来进入黄色的BorderPane,但仍允许点击绿色StackPane上实际的UI元素(例如按钮等可点击的东西)。

如何实现?


你真的需要绿色堆栈窗格吗?似乎你应该能够直接将其包含的UI元素添加到底层的堆栈窗格中。 - James_D
1个回答

13

您可以使用 stackPane.setPickOnBounds(false);。这意味着只有在单击堆叠面板的区域不透明时,堆叠面板才会被视为鼠标操作的目标(而不是默认行为,即如果鼠标单击在其边界内,则将其识别为鼠标操作的目标)。

以下是 SSCCE:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class ClickThroughStackPane extends Application {

    @Override
    public void start(Stage primaryStage) {
        Canvas canvas = new Canvas(400,400);
        canvas.setOnMouseClicked(e -> System.out.println("Mouse click: canvas"));
        HBox statusBar = new HBox(new Label("Status"));
        statusBar.setOnMouseClicked(e -> System.out.println("Mouse click: statusBar"));
        BorderPane borderPane = new BorderPane(canvas, statusBar, null, null, null);

        Button button = new Button("Click");
        button.setOnAction(e -> System.out.println("Button pressed"));
        StackPane stack = new StackPane(button);

        stack.setPickOnBounds(false);

        StackPane root = new StackPane(borderPane, stack);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

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

请注意,顶部堆栈窗格似乎是不必要的,因为您可以直接将其包含的UI元素添加到底层堆栈窗格中。前面的示例可以简单地重写为:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class ClickThroughStackPane extends Application {

    @Override
    public void start(Stage primaryStage) {
        Canvas canvas = new Canvas(400,400);
        canvas.setOnMouseClicked(e -> System.out.println("Mouse click: canvas"));
        HBox statusBar = new HBox(new Label("Status"));
        statusBar.setOnMouseClicked(e -> System.out.println("Mouse click: statusBar"));
        BorderPane borderPane = new BorderPane(canvas, statusBar, null, null, null);

        Button button = new Button("Click");
        button.setOnAction(e -> System.out.println("Button pressed"));

        StackPane root = new StackPane(borderPane, button);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

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

但是在你的第二个例子中,你没有调用setPickOnBounds(false),所以我怀疑它是否有效。 - mipa
2
@mipa SSCCE 的美妙之处在于你可以运行它并查看。在第二个示例中,我完全省略了“upper”堆栈面板,因此没有任何东西来拦截鼠标事件,但我仍然实现了相同的布局。我的观点是顶部堆栈面板似乎是不必要的。 - James_D
1
啊哈 - 我明白了。是我的错。我承认我没有运行这个例子 :-) - mipa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接