You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过屏幕坐标获取JavaFX的Stage?跨Stage事件传递需求

Cross-Stage Event Firing in JavaFX: Targeting Stages by Screen Coordinates

Great question! In JavaFX, there isn't a direct built-in API to retrieve a Stage by screen coordinates, but we can work around this by iterating through all open windows and checking if the target coordinates fall within their bounds. Let's break down the solution and fix your current implementation issues.

Core Problem in Your Current Code

Your existing onMouseClicked method fires the event on the sender stage's own node, which triggers the same onMouseClicked handler recursively—this is why you're seeing the InvocationTargetException. We need to instead:

  1. Locate the correct target Stage/Window at your simulated cursor's coordinates
  2. Find the exact node under those coordinates in the target Stage
  3. Fire the event on that target node (not the sender's node)

Step-by-Step Solution

1. Add a Helper Method to Locate the Target Window

First, create a method to scan all open windows and find the one that contains your target screen coordinates. We'll exclude the sender window itself and any popups (like your simulated cursor) to avoid false matches:

import javafx.stage.Window;
import javafx.geometry.Rectangle2D;

private Window getTargetWindow(double screenX, double screenY, Window senderWindow) {
    for (Window window : Window.getWindows()) {
        // Skip invisible windows, the sender window, and popups
        if (!window.isShowing() 
            || window.equals(senderWindow) 
            || window instanceof javafx.stage.Popup) {
            continue;
        }
        // Check if coordinates are within the window's screen bounds
        Rectangle2D windowBounds = new Rectangle2D(
            window.getX(), window.getY(), 
            window.getWidth(), window.getHeight()
        );
        if (windowBounds.contains(screenX, screenY)) {
            return window;
        }
    }
    return null;
}

2. Modify the onMouseClicked Method to Target the Correct Stage

Update your event handler to find the target window, locate the node under the coordinates, and fire the event correctly:

import javafx.scene.Point2D;
import javafx.stage.Window;

public void onMouseClicked(MouseEvent mouseEvent) {
    // Get the simulated cursor's screen coordinates
    double screenX = cursorPosX;
    double screenY = cursorPosY;

    // Get the sender's own window to exclude it from search
    Window senderWindow = ((Node) mouseEvent.getSource()).getScene().getWindow();
    Window targetWindow = getTargetWindow(screenX, screenY, senderWindow);

    if (targetWindow == null) {
        System.out.println("No target stage found at (" + screenX + ", " + screenY + ")");
        return;
    }

    // Convert screen coordinates to the target scene's local coordinates
    Scene targetScene = targetWindow.getScene();
    Point2D scenePoint = targetScene.screenToLocal(screenX, screenY);
    double sceneX = scenePoint.getX();
    double sceneY = scenePoint.getY();

    // Find the exact node under the coordinates in the target scene
    Node targetNode = targetScene.getRoot().pick(sceneX, sceneY);
    // Fallback to the scene root if no specific node is found
    if (targetNode == null) {
        targetNode = targetScene.getRoot();
    }

    // Convert scene coordinates to the target node's local coordinates
    Point2D localPoint = targetNode.sceneToLocal(sceneX, sceneY);
    double localX = localPoint.getX();
    double localY = localPoint.getY();

    // Create a properly configured MouseEvent for the target node
    MouseEvent clickEvent = new MouseEvent(
            MouseEvent.MOUSE_CLICKED,
            localX, localY,       // Node-local coordinates
            sceneX, sceneY,       // Scene coordinates
            MouseButton.PRIMARY,
            1,                    // Click count
            true, true, true, true,
            true, true, true, true,
            true, true,
            null                  // No event source needed here
    );

    // Fire the event on the target node
    targetNode.fireEvent(clickEvent);
    System.out.println("Successfully fired click event to: " + targetNode.getClass().getSimpleName());
}

3. Key Fixes & Explanations

  • Avoid Recursion: We explicitly exclude the sender window from the search, so we never fire the event on the sender's own node again.
  • Coordinate Conversion: JavaFX events rely on correct coordinate contexts (node-local, scene, screen). We convert the screen coordinates step-by-step to match the target node's local space.
  • Node Picking: Using scene.getRoot().pick() ensures we target the exact UI element under the cursor, not just the Stage itself.

Testing the Solution

When you run your modified code:

  1. Move the simulated cursor in the "Sender" stage over the "Receiver" stage
  2. Click in the "Sender" stage—you should see the "MOUSE CLICKED!" message from the Receiver's controller, with no recursive exceptions.

内容的提问来源于stack exchange,提问作者beid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:16:21