24

我一直在尝试使用以下鼠标侦听器在屏幕上移动未装饰的舞台:

  • 按下
  • 已发布
  • 拖拽

这些事件来自一个矩形。我的想法是移动未装饰的窗口,单击矩形并拖动所有窗口。

@FXML
受保护的无效onRectanglePressed(鼠标事件事件){
    X = primaryStage.getX() - event.getScreenX();
    Y = primaryStage.getY() - event.getScreenY();
}

@FXML
受保护的无效 onRectangleReleased(MouseEvent 事件) {
    primaryStage.setX(event.getScreenX());
    primaryStage.setY(event.getScreenY());
}

@FXML
受保护的无效 onRectangleDragged(MouseEvent 事件){
    primaryStage.setX(event.getScreenX() + X);
    primaryStage.setY(event.getScreenY() + Y);
}

我对这些事件所做的只是当我按下矩形并开始拖动窗口时,它会移动一点。但是,当我释放按钮时,窗口会移动到矩形所在的位置。

提前致谢。

4

5 回答 5

29

我在一个未装饰的窗口中创建了一个动画时钟示例,您可以拖动它。

示例中的相关代码是:

// allow the clock background to be used to drag the clock around.
final Delta dragDelta = new Delta();
layout.setOnMousePressed(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    // record a delta distance for the drag and drop operation.
    dragDelta.x = stage.getX() - mouseEvent.getScreenX();
    dragDelta.y = stage.getY() - mouseEvent.getScreenY();
  }
});
layout.setOnMouseDragged(new EventHandler<MouseEvent>() {
  @Override public void handle(MouseEvent mouseEvent) {
    stage.setX(mouseEvent.getScreenX() + dragDelta.x);
    stage.setY(mouseEvent.getScreenY() + dragDelta.y);
  }
});

...

// records relative x and y co-ordinates.
class Delta { double x, y; } 

代码看起来和你的很相似,所以不太清楚为什么你的代码不适合你。

于 2012-08-02T15:53:45.293 回答
14

我正在使用此解决方案通过拖动任何包含的节点来拖动未装饰的阶段。

private void addDraggableNode(final Node node) {

    node.setOnMousePressed(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent me) {
            if (me.getButton() != MouseButton.MIDDLE) {
                initialX = me.getSceneX();
                initialY = me.getSceneY();
            }
        }
    });

    node.setOnMouseDragged(new EventHandler<MouseEvent>() {
        @Override
        public void handle(MouseEvent me) {
            if (me.getButton() != MouseButton.MIDDLE) {
                node.getScene().getWindow().setX(me.getScreenX() - initialX);
                node.getScene().getWindow().setY(me.getScreenY() - initialY);
            }
        }
    });
}
于 2012-10-18T19:07:32.220 回答
4

根据jewelsea 的回复,我做了两个lamba 表达式以在我的start() 方法中直接在场景中设置MouseListeners。工作正常 :)

private double xOffset;
private double yOffset;
         /*
        The two following lambda expressions makes it possible to move the application without the standard StageStyle
         */
        //Lambda mouse event handler
        scene.setOnMousePressed(event -> {
            xOffset = primaryStage.getX() - event.getScreenX();
            yOffset = primaryStage.getY() - event.getScreenY();
        });
        //Lambda mouse event handler
        scene.setOnMouseDragged(event -> {
            primaryStage.setX(event.getScreenX() + xOffset);
            primaryStage.setY(event.getScreenY() + yOffset);
        });enter code here
于 2015-11-30T18:46:26.503 回答
3

我的猜测是你的:

onRectangleReleased()

正在传递与您相同的坐标

onRectanglePressed()

发生这种情况是因为如文档中所述,来自 MouseEvent 类的 getX() 方法返回

事件相对于 MouseEvent 源的水平位置。

然后,当您释放鼠标时,它实际上会将矩形放置在您第一次按下鼠标时的位置。

顺便说一句,我使用内部带有 Rectangle 的 StackPane,然后应用以下代码:

private void addDragListeners(final Node n){
       n.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent me) {
                if(me.getButton()!=MouseButton.MIDDLE)
                {
                    initialX = me.getSceneX();
                    initialY = me.getSceneY();
                }
                else
                {
                    n.getScene().getWindow().centerOnScreen();
                    initialX = n.getScene().getWindow().getX();
                    initialY = n.getScene().getWindow().getY();
                }

            }
       });

       n.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent me) {
                if(me.getButton()!=MouseButton.MIDDLE)
                {
                    n.getScene().getWindow().setX( me.getScreenX() - initialX );
                    n.getScene().getWindow().setY( me.getScreenY() - initialY);
                }
            }
        });
}

addDragListeners(mainStackPane);

除此之外,我使用鼠标中键使我的窗口在屏幕上居中。我希望它有所帮助。干杯!

于 2012-08-02T23:48:56.213 回答
1
double x, y;

private void addDragListeners(final Node n, Stage primaryStage){

    n.setOnMousePressed((MouseEvent mouseEvent) -> {
        this.x = n.getScene().getWindow().getX() - mouseEvent.getScreenX();
        this.y = n.getScene().getWindow().getY() - mouseEvent.getScreenY();
    });

    n.setOnMouseDragged((MouseEvent mouseEvent) -> {
        primaryStage.setX(mouseEvent.getScreenX() + this.x);
        primaryStage.setY(mouseEvent.getScreenY() + this.y);
    });
}

public void start(Stage primaryStage) {

    try {

        ...

        addDragListeners(mainPane, primaryStage);

    } catch (Exception e) {
        e.printStackTrace(System.out);
    }

}
于 2014-10-15T03:56:27.553 回答