Skip to content

Instantly share code, notes, and snippets.

@cannibalsticky
Last active January 6, 2021 10:12
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cannibalsticky/a3057d6e9c1f029d99e6bc95f9b3340e to your computer and use it in GitHub Desktop.
Save cannibalsticky/a3057d6e9c1f029d99e6bc95f9b3340e to your computer and use it in GitHub Desktop.
DragResizerXY can be used to add mouse listeners to a Region and make it resizable by the user by clicking and dragging the border in the same way as a window. Height and Width are both working.
import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
/**
* {@link DragResizerXY} can be used to add mouse listeners to a {@link Region}
* and make it resizable by the user by clicking and dragging the border in the
* same way as a window.
* <p>
* Height and Width resizing is working (hopefully) properly
*
* <pre>
* DragResizer.makeResizable(myAnchorPane);
* </pre>
*
* @author Cannibalsticky (modified from the original DragResizer created by AndyTill)
*
*/
public class DragResizerXY {
/**
* The margin around the control that a user can click in to start resizing
* the region.
*/
private static final int RESIZE_MARGIN = 10;
private final Region region;
private double y;
private double x;
private boolean initMinHeight;
private boolean initMinWidth;
private boolean draggableZoneX, draggableZoneY;
private boolean dragging;
private DragResizerXY(Region aRegion) {
region = aRegion;
}
public static void makeResizable(Region region) {
final DragResizerXY resizer = new DragResizerXY(region);
region.setOnMousePressed(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
resizer.mousePressed(event);
}
});
region.setOnMouseDragged(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
resizer.mouseDragged(event);
}
});
region.setOnMouseMoved(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
resizer.mouseOver(event);
}
});
region.setOnMouseReleased(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
resizer.mouseReleased(event);
}
});
}
protected void mouseReleased(MouseEvent event) {
dragging = false;
region.setCursor(Cursor.DEFAULT);
}
protected void mouseOver(MouseEvent event) {
if (isInDraggableZone(event) || dragging) {
if (draggableZoneY) {
region.setCursor(Cursor.S_RESIZE);
}
if (draggableZoneX) {
region.setCursor(Cursor.E_RESIZE);
}
} else {
region.setCursor(Cursor.DEFAULT);
}
}
//had to use 2 variables for the controll, tried without, had unexpected behaviour (going big was ok, going small nope.)
protected boolean isInDraggableZone(MouseEvent event) {
draggableZoneY = (boolean)(event.getY() > (region.getHeight() - RESIZE_MARGIN));
draggableZoneX = (boolean)(event.getX() > (region.getWidth() - RESIZE_MARGIN));
return (draggableZoneY || draggableZoneX);
}
protected void mouseDragged(MouseEvent event) {
if (!dragging) {
return;
}
if (draggableZoneY) {
double mousey = event.getY();
double newHeight = region.getMinHeight() + (mousey - y);
region.setMinHeight(newHeight);
y = mousey;
}
if (draggableZoneX) {
double mousex = event.getX();
double newWidth = region.getMinWidth() + (mousex - x);
region.setMinWidth(newWidth);
x = mousex;
}
}
protected void mousePressed(MouseEvent event) {
// ignore clicks outside of the draggable margin
if (!isInDraggableZone(event)) {
return;
}
dragging = true;
// make sure that the minimum height is set to the current height once,
// setting a min height that is smaller than the current height will
// have no effect
if (!initMinHeight) {
region.setMinHeight(region.getHeight());
initMinHeight = true;
}
y = event.getY();
if (!initMinWidth) {
region.setMinWidth(region.getWidth());
initMinWidth = true;
}
x = event.getX();
}
}
@GeoffCapper
Copy link

Thanks for this! If a prefHeight/prefWidth are set on the region they will currently act as a minimum, at least on the BorderPane I was just trying it with. If you add region.setPrefHeight(newHeight) etc into the mousePressed method it will overcome this limit.

@rutsatz
Copy link

rutsatz commented Jun 30, 2018

Thank you for that! It was very useful to me. I also had the need to move the component with the mouse. So I made some changes, adding that too. If someone wants it, below is the link to the file.
https://gist.github.com/rutsatz/bb80e9535ff665276c5128260428eaa8
Hugs!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment