Moving an undecorated stage in javafx 2
Asked Answered
C

5

26

I've been trying to move an undecorated stage around the screen, by using the following mouse listeners:

  • onPressed
  • onReleased
  • onDragged

These events are from a rectangle. My idea is to move the undecorated window clicking on the rectangle and dragging all the window.

@FXML
protected void onRectanglePressed(MouseEvent event) {
    X = primaryStage.getX() - event.getScreenX();
    Y = primaryStage.getY() - event.getScreenY();
}

@FXML
protected void onRectangleReleased(MouseEvent event) {
    primaryStage.setX(event.getScreenX());
    primaryStage.setY(event.getScreenY());
}

@FXML
protected void onRectangleDragged(MouseEvent event) {
    primaryStage.setX(event.getScreenX() + X);
    primaryStage.setY(event.getScreenY() + Y);
}

All that I've got with these events is when I press the rectangle and start to drag the window, it moves a little bit. But, when I release the button, the window is moved to where the rectangle is.

Thanks in advance.

Calx answered 2/8, 2012 at 14:51 Comment(1)
No need to handle the event onRectangleReleased.Adsorbate
S
32

I created a sample of an animated clock in an undecorated window which you can drag around.

Relevant code from the sample is:

// 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; } 

Code looks pretty similar to yours, so not quite sure why your code is not working for you.

Senghor answered 2/8, 2012 at 15:53 Comment(4)
Yes, it's pretty the same. finally found the solution, my mistake was using the wrong event. I was using scene builder. But implementing the setOnMouseDragged, everything goes perfect. Thank you!Calx
I've noticed that this method has a lower refresh rate than the system window drag. Wish I knew how to use the system window position relocator.Crutch
setting stage to undecorated removes window 10 support for quick edge resizingCrutch
@Crutch #19455559Malaysia
L
14

I'm using this solution for dragging undecoraqted stages by dragging any contained node.

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);
            }
        }
    });
}
Lem answered 18/10, 2012 at 19:7 Comment(0)
A
4

Based on jewelsea's reply i made two lamba expressions to set the MouseListeners directly on the scene in my start() method. Works fine :)

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
Agulhas answered 30/11, 2015 at 18:46 Comment(0)
D
3

My guess is that your:

onRectangleReleased()

is passing the very same coordinates from your

onRectanglePressed()

This happens because as stated in the documentation the getX() method from the MouseEvent class returns

Horizontal position of the event relative to the origin of the MouseEvent's source.

then, when you release your mouse it actually puts your rectangle in the place it was when you first mouse pressed.

BTW, I use a StackPane with a Rectangle inside and then apply the following code:

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);

Besides that, I use the Middle Mouse Button to center my Window on the screen. I hoped it helped. Cheers!

Digraph answered 2/8, 2012 at 23:48 Comment(1)
Thank you. I was creating the GUI with the scene builder, and I was using the wrong drag event. I implement onMouseDragged and all works. Thank you!Calx
B
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);
    }

}
Bowling answered 15/10, 2014 at 3:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.