首页 > 解决方案 > 如何从 X、Y 坐标中检索舞台?

问题描述

我正在尝试将 JavaFX 中的事件从一个离散阶段发送到另一个阶段。这些 Stage 没有任何共同的父级链接,也不是另一个的子级,因此没有层次结构或树可供我尝试遍历以找到 Stage。

在这一点上,我试图能够从我的屏幕上的 X、Y 坐标获取舞台。我认为这将是一种获取可以用作 EventTarget 的东西的方法。

但是,我对这个特定问题一无所获。我发现的问题都涉及同一父级的组件之间的事件触发。实际上有没有办法从坐标中获取舞台?

到目前为止,我已经尝试获取一个节点并触发该事件,但它会导致 InvocationReflectionException。我认为这是因为我单击的节点(显然)是 MouseEvent 的目标,并且最终会调用自身直到它中断?

除此之外,我尝试过 stage.fireEvent(),但实际上什么也没做。

这是我正在尝试做的示例。

示例.fxml

<?import javafx.scene.layout.GridPane?>
<GridPane fx:controller="sample.Controller"
    xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10 vgap="10"
    onMouseClicked="#onMouseClicked">
</GridPane>

控制器.java

package sample;

import javafx.scene.input.MouseEvent;

public class Controller
{
    //Just noting that it has been clicked
    public void onMouseClicked(MouseEvent mouseEvent)
    {
        System.out.println("MOUSE CLICKED!");
    {
}

例子.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="sample.ExController"
            prefHeight="400.0" prefWidth="600.0"
            onMouseClicked="#onMouseClicked"
            onMouseEntered="#onMouseEntered"
            onMouseMoved="#onMouseMoved">
</AnchorPane>

ExController.java

package sample;

import javafx.geometry.Rectangle2D;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.stage.Popup;
import javafx.stage.Screen;

//This is the controller that fires the mouse click Event
public class ExController
{
    double cursorPosX;
    double cursorPosY;
    double mouseEnterX;
    double mouseEnterY;

    //Fake cursor placeholder
    Popup popupCursor;

    //Just fills the placeholder
    Label label = new Label();

    //Creates a placeholder fake cursor
    //This can be safely ignored for the purposes of the question
    public void onMouseEntered(MouseEvent mouseEvent)
    {
        mouseEnterX = mouseEvent.getX();
        mouseEnterY = mouseEvent.getY();

        if(popupCursor == null)
        {
            //Initial Cursor position
            cursorPosX = 0;
            cursorPosY = 0;

            //Set up label stuff
            label.setPrefHeight(100);
            label.setPrefWidth(100);
            label.setStyle("-fx-background-color: #" + "0f0f0f);

            //Create popup window
            popupCursor = new Popup();
            popupCursor.getContent().add(label);
            popupCursor.show((Node)mouseEvent.getSource(), 100, 100);
        }
    }
    //This is a poor attempt at making a fake cursor move
    //This can also be safely ignored
    public void onMouseMoved(MouseEvent mouseEvent)
    {
        if(popupCursor != null)
        {
            Rectangle2D bounds = Screen.getPrimary().getVisualBounds();

            //delta between mouseEvent and the point the screen was entered at
            double deltaX = mouseEvent.getSceneX() - mouseEnterX;
            double deltaY = mouseEvent.getSceneY() - mouseEnterY;

            //Movement increment - poorly done, but sorta functional
            double incrementX = (bounds.getWidth() / 500);
            double incrementY = (bounds.getHeight() / 500);

            if(deltaX > 0)
            {
                cursorPosX += incrementX;
            }
            else if(deltaX < 0)
            {
                cursorPosX -= incrementX;
            }

            if(deltaY > 0)
            {
                cursorPosY += incrementY;
            }
            else if(deltaY < 0)
            {
                cursorPosY -= incrementY;
            }

            if(cursorPosX < bounds.getMaxX() || cursorPosX > bounds.getMinX())
            {
                popupCursor.setX(cursorPosX);
            }
            if(cursorPosY < bounds.getMaxY() || cursorPosY > bounds.getMinY())
            {
                popupCursor.setY(cursorPosY);
            }

            mouseEvent.consume();
        }
    }

    //THIS is the problem method.  It creates a mouse event and attempts
    // to fire it off to a different Stage it literally knows nothing about
    public void onMouseClicked(MouseEvent mouseEvent)
    {
        //Creating a Mouse Event to fire
        MouseEvent click = new MouseEvent(MouseEvent.MOUSE_CLICKED,
            cursorPosX, cursorPosY, cursorPosX, cursorPosY,
            MouseButton.PRIMARY, 1, true, true, true, true, true,
            true, true, true, true, true, null);

        //Causes InvocationReflectionError
        Node source = (Node) mouseEvent.getSource(); 
        source.fireEvent(click);
    }
}

主.java

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        //Stage 1
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Receiver");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        //Stage 2
        Parent otherRoot =
            FXMLLoader.load(getClass().getResource("example.fxml"));
        Stage otherStage = new Stage();
        otherStage.setTitle("Sender");
        otherStage.setScene(new Scene(otherRoot, 300, 275));
        otherStage.show();
    }

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

标签: javajavafxjavafx-11

解决方案


推荐阅读