Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow user to resize an undecorated Stage

Tags:

I am working on making a screen recorder in JavaFX and one utility that is mandatory in the screen recorder is to let the user define how much area to record.

I managed to make an undecorated , semi-transparent Stage that can be dragged around to define the area and added a close button to let the user confirm the area which is to be recorded.

Now, how do I let the user resize the stage by dragging it by its edges ?

SSCCE:

package draggable;  import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Pos; import javafx.geometry.Rectangle2D; import javafx.scene.Scene; import javafx.scene.SceneBuilder; import javafx.scene.control.Button; import javafx.scene.control.ButtonBuilder; import javafx.scene.input.MouseEvent; import javafx.scene.layout.StackPane; import javafx.scene.layout.StackPaneBuilder; import javafx.scene.paint.Color; import javafx.stage.Screen; import javafx.stage.Stage; import javafx.stage.StageStyle;  public class DraggableStage extends Application{      Button close;     StackPane holder;     Rectangle2D maxBounds;     Scene theScene;      double pressedX;     double pressedY;     double draggedX;     double draggedY;      @Override     public void start(Stage stage) throws Exception {         final Stage theStage = stage;          // determine how big the screen is         maxBounds = Screen.getPrimary().getVisualBounds();           //create the close button         close = ButtonBuilder                 .create()                 .text("Close")                 .build();          //create the StackPane holder for the button         holder = StackPaneBuilder                     .create()                     .alignment(Pos.CENTER)                     .children(close)                     .build();          // you cannot resize the screen beyond the max resolution of the screen         holder.setMaxSize(maxBounds.getWidth(), maxBounds.getHeight());          //you cannot resize under half the width and height of the screen         holder.setMinSize(maxBounds.getWidth() / 2,maxBounds.getHeight() / 2);          //the scene where it all happens         theScene = SceneBuilder                       .create()                       .root(holder)                       .width(maxBounds.getWidth() / 2)                       .height(maxBounds.getHeight() / 2)                       .build();          // add the button listeners         close.setOnAction(new EventHandler<ActionEvent>(){             @Override             public void handle(ActionEvent event) {                 theStage.close();             }         });          // add the drag and press listener for the StackPane         holder.setOnMousePressed(new EventHandler<MouseEvent>(){             @Override             public void handle(MouseEvent e) {                 pressedX = e.getX();                 pressedY = e.getY();             }         });          holder.setOnMouseDragged(new EventHandler<MouseEvent>(){             @Override             public void handle(MouseEvent e) {                 draggedX = e.getX();                 draggedY = e.getY();                  double differenceX = draggedX - pressedX;                 double differenceY = draggedY - pressedY;                  theStage.setX(theStage.getX() + differenceX);                 theStage.setY(theStage.getY() + differenceY);              }         });          //the mandatory mumbo jumbo         theScene.setFill(Color.rgb(128, 128, 128, 0.5));         stage.initStyle(StageStyle.TRANSPARENT);         stage.setScene(theScene);         stage.sizeToScene();         stage.show();     }      public static void main(String[] args) {         Application.launch("draggable.DraggableStage");     } }   

Image:
enter image description here

like image 668
An SO User Avatar asked Oct 18 '13 16:10

An SO User


1 Answers

I created a ResizeHelper class which can help you in that case, usage:

ResizeHelper.addResizeListener(yourStage); 

the helper class:

import javafx.collections.ObservableList; import javafx.event.EventHandler; import javafx.event.EventType; import javafx.scene.Cursor; import javafx.scene.Node; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.input.MouseEvent; import javafx.stage.Stage;  //created by Alexander Berg public class ResizeHelper {      public static void addResizeListener(Stage stage) {         ResizeListener resizeListener = new ResizeListener(stage);         stage.getScene().addEventHandler(MouseEvent.MOUSE_MOVED, resizeListener);         stage.getScene().addEventHandler(MouseEvent.MOUSE_PRESSED, resizeListener);         stage.getScene().addEventHandler(MouseEvent.MOUSE_DRAGGED, resizeListener);         stage.getScene().addEventHandler(MouseEvent.MOUSE_EXITED, resizeListener);         stage.getScene().addEventHandler(MouseEvent.MOUSE_EXITED_TARGET, resizeListener);         ObservableList<Node> children = stage.getScene().getRoot().getChildrenUnmodifiable();         for (Node child : children) {             addListenerDeeply(child, resizeListener);         }     }      public static void addListenerDeeply(Node node, EventHandler<MouseEvent> listener) {         node.addEventHandler(MouseEvent.MOUSE_MOVED, listener);         node.addEventHandler(MouseEvent.MOUSE_PRESSED, listener);         node.addEventHandler(MouseEvent.MOUSE_DRAGGED, listener);         node.addEventHandler(MouseEvent.MOUSE_EXITED, listener);         node.addEventHandler(MouseEvent.MOUSE_EXITED_TARGET, listener);         if (node instanceof Parent) {             Parent parent = (Parent) node;             ObservableList<Node> children = parent.getChildrenUnmodifiable();             for (Node child : children) {                 addListenerDeeply(child, listener);             }         }     }      static class ResizeListener implements EventHandler<MouseEvent> {         private Stage stage;         private Cursor cursorEvent = Cursor.DEFAULT;         private int border = 4;         private double startX = 0;         private double startY = 0;          public ResizeListener(Stage stage) {             this.stage = stage;         }          @Override         public void handle(MouseEvent mouseEvent) {             EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType();             Scene scene = stage.getScene();              double mouseEventX = mouseEvent.getSceneX(),                     mouseEventY = mouseEvent.getSceneY(),                    sceneWidth = scene.getWidth(),                    sceneHeight = scene.getHeight();              if (MouseEvent.MOUSE_MOVED.equals(mouseEventType) == true) {                 if (mouseEventX < border && mouseEventY < border) {                     cursorEvent = Cursor.NW_RESIZE;                 } else if (mouseEventX < border && mouseEventY > sceneHeight - border) {                     cursorEvent = Cursor.SW_RESIZE;                 } else if (mouseEventX > sceneWidth - border && mouseEventY < border) {                     cursorEvent = Cursor.NE_RESIZE;                 } else if (mouseEventX > sceneWidth - border && mouseEventY > sceneHeight - border) {                     cursorEvent = Cursor.SE_RESIZE;                 } else if (mouseEventX < border) {                     cursorEvent = Cursor.W_RESIZE;                 } else if (mouseEventX > sceneWidth - border) {                     cursorEvent = Cursor.E_RESIZE;                 } else if (mouseEventY < border) {                     cursorEvent = Cursor.N_RESIZE;                 } else if (mouseEventY > sceneHeight - border) {                     cursorEvent = Cursor.S_RESIZE;                 } else {                     cursorEvent = Cursor.DEFAULT;                 }                 scene.setCursor(cursorEvent);             } else if(MouseEvent.MOUSE_EXITED.equals(mouseEventType) || MouseEvent.MOUSE_EXITED_TARGET.equals(mouseEventType)){                 scene.setCursor(Cursor.DEFAULT);             } else if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType) == true) {                 startX = stage.getWidth() - mouseEventX;                 startY = stage.getHeight() - mouseEventY;             } else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) == true) {                 if (Cursor.DEFAULT.equals(cursorEvent) == false) {                     if (Cursor.W_RESIZE.equals(cursorEvent) == false && Cursor.E_RESIZE.equals(cursorEvent) == false) {                         double minHeight = stage.getMinHeight() > (border*2) ? stage.getMinHeight() : (border*2);                         if (Cursor.NW_RESIZE.equals(cursorEvent) == true || Cursor.N_RESIZE.equals(cursorEvent) == true || Cursor.NE_RESIZE.equals(cursorEvent) == true) {                             if (stage.getHeight() > minHeight || mouseEventY < 0) {                                 stage.setHeight(stage.getY() - mouseEvent.getScreenY() + stage.getHeight());                                 stage.setY(mouseEvent.getScreenY());                             }                         } else {                             if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {                                 stage.setHeight(mouseEventY + startY);                             }                         }                     }                      if (Cursor.N_RESIZE.equals(cursorEvent) == false && Cursor.S_RESIZE.equals(cursorEvent) == false) {                         double minWidth = stage.getMinWidth() > (border*2) ? stage.getMinWidth() : (border*2);                         if (Cursor.NW_RESIZE.equals(cursorEvent) == true || Cursor.W_RESIZE.equals(cursorEvent) == true || Cursor.SW_RESIZE.equals(cursorEvent) == true) {                             if (stage.getWidth() > minWidth || mouseEventX < 0) {                                 stage.setWidth(stage.getX() - mouseEvent.getScreenX() + stage.getWidth());                                 stage.setX(mouseEvent.getScreenX());                             }                         } else {                             if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {                                 stage.setWidth(mouseEventX + startX);                             }                         }                     }                 }              }         }     } } 
like image 185
Alexander.Berg Avatar answered Nov 11 '22 08:11

Alexander.Berg