Lit*_*ild 17 java stage scene javafx-2
我正在制作JavaFX中的屏幕录像机,并且屏幕录像机中必需的一个实用程序是让用户定义要记录的区域.
我设法做了一个未修饰的,半透明的Stage,可以拖动来定义区域并添加一个close按钮让用户确认要记录的区域.
现在,如何通过拖动边缘来让用户调整舞台的大小?
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");
}
}
Run Code Online (Sandbox Code Playgroud)
图片:

Ale*_*erg 34
我创建了一个ResizeHelper类,在这种情况下可以帮助你,用法:
ResizeHelper.addResizeListener(yourStage);
Run Code Online (Sandbox Code Playgroud)
助手类:
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);
}
}
}
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我更新了 @Alexander.Berg 的 ResizeHelper 类的 @Yevhenii.Kanivets 的更新版本。这包括拖动场景的能力,以及我发现的 ResizeHelper 的最佳实现。还将最小舞台大小设置为高度为 1 和宽度为 1 而不是 0,因为如果它们保持为 0,则会出现错误。
有人仍然可以改进这个答案。SW、W、NW、N 和 NE 边缘不会平滑地调整大小,尽管这是一个小问题。从这些边缘调整大小时,场景也可能会稍微移动。它们应该像 S、SE 和 E 边缘一样平滑地调整大小。后面的边缘不会改变场景。
我不能代表 @MK 的实现,因为我没有使用 Kotlin,但如果你是,我会先试一试。
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;
/**
* Util class to handle window resizing when a stage style set to StageStyle.UNDECORATED.
* Includes dragging of the stage.
* Original on 6/13/14.
* Updated on 8/15/17.
* Updated on 12/19/19.
*
* @author Alexander.Berg
* @author Evgenii Kanivets
* @author Zachary Perales
*/
public class ResizeHelper {
public static void addResizeListener(Stage stage) {
addResizeListener(stage, 1, 1, Double.MAX_VALUE, Double.MAX_VALUE);
}
public static void addResizeListener(Stage stage, double minWidth, double minHeight, double maxWidth, double maxHeight) {
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);
resizeListener.setMinWidth(minWidth);
resizeListener.setMinHeight(minHeight);
resizeListener.setMaxWidth(maxWidth);
resizeListener.setMaxHeight(maxHeight);
ObservableList<Node> children = stage.getScene().getRoot().getChildrenUnmodifiable();
for (Node child : children) {
addListenerDeeply(child, resizeListener);
}
}
private 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 boolean resizing = true;
private int border = 4;
private double startX = 0;
private double startY = 0;
private double screenOffsetX = 0;
private double screenOffsetY = 0;
// Max and min sizes for controlled stage
private double minWidth;
private double maxWidth;
private double minHeight;
private double maxHeight;
public ResizeListener(Stage stage) {
this.stage = stage;
}
public void setMinWidth(double minWidth) {
this.minWidth = minWidth;
}
public void setMaxWidth(double maxWidth) {
this.maxWidth = maxWidth;
}
public void setMinHeight(double minHeight) {
this.minHeight = minHeight;
}
public void setMaxHeight(double maxHeight) {
this.maxHeight = maxHeight;
}
@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)) {
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)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
if (!Cursor.DEFAULT.equals(cursorEvent)) {
resizing = true;
if (!Cursor.W_RESIZE.equals(cursorEvent) && !Cursor.E_RESIZE.equals(cursorEvent)) {
double minHeight = stage.getMinHeight() > (border * 2) ? stage.getMinHeight() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.N_RESIZE.equals(cursorEvent)
|| Cursor.NE_RESIZE.equals(cursorEvent)) {
if (stage.getHeight() > minHeight || mouseEventY < 0) {
setStageHeight(stage.getY() - mouseEvent.getScreenY() + stage.getHeight());
stage.setY(mouseEvent.getScreenY() );
}
} else {
if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
setStageHeight(mouseEventY + startY);
}
}
}
if (!Cursor.N_RESIZE.equals(cursorEvent) && !Cursor.S_RESIZE.equals(cursorEvent)) {
double minWidth = stage.getMinWidth() > (border * 2) ? stage.getMinWidth() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.W_RESIZE.equals(cursorEvent)
|| Cursor.SW_RESIZE.equals(cursorEvent)) {
if (stage.getWidth() > minWidth || mouseEventX < 0) {
setStageWidth(stage.getX() - mouseEvent.getScreenX() + stage.getWidth());
stage.setX(mouseEvent.getScreenX());
}
} else {
if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
setStageWidth(mouseEventX + startX);
}
}
}
resizing = false;
}
}
if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType) && Cursor.DEFAULT.equals(cursorEvent)) {
resizing = false;
screenOffsetX = stage.getX() - mouseEvent.getScreenX();
screenOffsetY = stage.getY() - mouseEvent.getScreenY();
}
if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) && Cursor.DEFAULT.equals(cursorEvent) && resizing == false) {
stage.setX(mouseEvent.getScreenX() + screenOffsetX);
stage.setY(mouseEvent.getScreenY() + screenOffsetY);
}
}
private void setStageWidth(double width) {
width = Math.min(width, maxWidth);
width = Math.max(width, minWidth);
stage.setWidth(width);
}
private void setStageHeight(double height) {
height = Math.min(height, maxHeight);
height = Math.max(height, minHeight);
stage.setHeight(height);
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我已更新此代码以不拖动任何滚动条,因为没有人想要该功能,我需要自己将其删除。如果您遇到需要,通过比较我在此处提交的两个代码,应该很容易禁止拖动其他控件。
请注意,如果不允许的控件位于场景的边缘,则需要将其包裹在可拖动的内容中以访问在这些边缘上调整大小。
public class ResizeHelper {
static boolean isScrollbar = false;
public static void addResizeListener(Stage stage) {
addResizeListener(stage, 1, 1, Double.MAX_VALUE, Double.MAX_VALUE);
}
public static void addResizeListener(Stage stage, double minWidth, double minHeight, double maxWidth, double maxHeight) {
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);
resizeListener.setMinWidth(minWidth);
resizeListener.setMinHeight(minHeight);
resizeListener.setMaxWidth(maxWidth);
resizeListener.setMaxHeight(maxHeight);
ObservableList<Node> children = stage.getScene().getRoot().getChildrenUnmodifiable();
for (Node child : children) {
if (child instanceof ScrollBar) {
isScrollbar = true;
} else if (!(child instanceof ScrollBar)) {
isScrollbar = false;
addListenerDeeply(child, resizeListener);
}
}
}
private 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) {
if (child instanceof ScrollBar) {
isScrollbar = true;
} else if (!(child instanceof ScrollBar)) {
isScrollbar = false;
addListenerDeeply(child, listener);
}
}
}
}
static class ResizeListener implements EventHandler<MouseEvent> {
private Stage stage;
private Cursor cursorEvent = Cursor.DEFAULT;
private boolean resizing = true;
private int border = 4;
private double startX = 0;
private double startY = 0;
private double screenOffsetX = 0;
private double screenOffsetY = 0;
// Max and min sizes for controlled stage
private double minWidth;
private double maxWidth;
private double minHeight;
private double maxHeight;
public ResizeListener(Stage stage) {
this.stage = stage;
}
public void setMinWidth(double minWidth) {
this.minWidth = minWidth;
}
public void setMaxWidth(double maxWidth) {
this.maxWidth = maxWidth;
}
public void setMinHeight(double minHeight) {
this.minHeight = minHeight;
}
public void setMaxHeight(double maxHeight) {
this.maxHeight = maxHeight;
}
@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) && stage.isMaximized() == false ) {
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)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
if (!Cursor.DEFAULT.equals(cursorEvent)) {
resizing = true;
if (!Cursor.W_RESIZE.equals(cursorEvent) && !Cursor.E_RESIZE.equals(cursorEvent)) {
double minHeight = stage.getMinHeight() > (border * 2) ? stage.getMinHeight() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.N_RESIZE.equals(cursorEvent)
|| Cursor.NE_RESIZE.equals(cursorEvent)) {
if (stage.getHeight() > minHeight || mouseEventY < 0) {
setStageHeight(stage.getY() - mouseEvent.getScreenY() + stage.getHeight());
stage.setY(mouseEvent.getScreenY() );
}
} else {
if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
setStageHeight(mouseEventY + startY);
}
}
}
if (!Cursor.N_RESIZE.equals(cursorEvent) && !Cursor.S_RESIZE.equals(cursorEvent)) {
double minWidth = stage.getMinWidth() > (border * 2) ? stage.getMinWidth() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.W_RESIZE.equals(cursorEvent)
|| Cursor.SW_RESIZE.equals(cursorEvent)) {
if (stage.getWidth() > minWidth || mouseEventX < 0) {
setStageWidth(stage.getX() - mouseEvent.getScreenX() + stage.getWidth());
stage.setX(mouseEvent.getScreenX());
}
} else {
if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
setStageWidth(mouseEventX + startX);
}
}
}
resizing = false;
}
}
if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType) && Cursor.DEFAULT.equals(cursorEvent) ) {
resizing = false;
screenOffsetX = stage.getX() - mouseEvent.getScreenX();
screenOffsetY = stage.getY() - mouseEvent.getScreenY();
}
if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) && Cursor.DEFAULT.equals(cursorEvent) && resizing == false) {
stage.setX(mouseEvent.getScreenX() + screenOffsetX);
stage.setY(mouseEvent.getScreenY() + screenOffsetY);
}
}
private void setStageWidth(double width) {
width = Math.min(width, maxWidth);
width = Math.max(width, minWidth);
stage.setWidth(width);
}
private void setStageHeight(double height) {
height = Math.min(height, maxHeight);
height = Math.max(height, minHeight);
stage.setHeight(height);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是@Alexander.Berg 发布的 ResizeHelper 的更新版本,它支持最小和最大阶段大小。
package sem.helper;
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;
/**
* Util class to handle window resizing when a stage style set to StageStyle.UNDECORATED.
* Created on 8/15/17.
*
* @author Evgenii Kanivets
*/
public class ResizeHelper {
public static void addResizeListener(Stage stage) {
addResizeListener(stage, 0, 0, Double.MAX_VALUE, Double.MAX_VALUE);
}
public static void addResizeListener(Stage stage, double minWidth, double minHeight, double maxWidth, double maxHeight) {
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);
resizeListener.setMinWidth(minWidth);
resizeListener.setMinHeight(minHeight);
resizeListener.setMaxWidth(maxWidth);
resizeListener.setMaxHeight(maxHeight);
ObservableList<Node> children = stage.getScene().getRoot().getChildrenUnmodifiable();
for (Node child : children) {
addListenerDeeply(child, resizeListener);
}
}
private 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;
// Max and min sizes for controlled stage
private double minWidth;
private double maxWidth;
private double minHeight;
private double maxHeight;
public ResizeListener(Stage stage) {
this.stage = stage;
}
public void setMinWidth(double minWidth) {
this.minWidth = minWidth;
}
public void setMaxWidth(double maxWidth) {
this.maxWidth = maxWidth;
}
public void setMinHeight(double minHeight) {
this.minHeight = minHeight;
}
public void setMaxHeight(double maxHeight) {
this.maxHeight = maxHeight;
}
@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)) {
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)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
if (!Cursor.DEFAULT.equals(cursorEvent)) {
if (!Cursor.W_RESIZE.equals(cursorEvent) && !Cursor.E_RESIZE.equals(cursorEvent)) {
double minHeight = stage.getMinHeight() > (border * 2) ? stage.getMinHeight() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.N_RESIZE.equals(cursorEvent)
|| Cursor.NE_RESIZE.equals(cursorEvent)) {
if (stage.getHeight() > minHeight || mouseEventY < 0) {
setStageHeight(stage.getY() - mouseEvent.getScreenY() + stage.getHeight());
stage.setY(mouseEvent.getScreenY());
}
} else {
if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
setStageHeight(mouseEventY + startY);
}
}
}
if (!Cursor.N_RESIZE.equals(cursorEvent) && !Cursor.S_RESIZE.equals(cursorEvent)) {
double minWidth = stage.getMinWidth() > (border * 2) ? stage.getMinWidth() : (border * 2);
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.W_RESIZE.equals(cursorEvent)
|| Cursor.SW_RESIZE.equals(cursorEvent)) {
if (stage.getWidth() > minWidth || mouseEventX < 0) {
setStageWidth(stage.getX() - mouseEvent.getScreenX() + stage.getWidth());
stage.setX(mouseEvent.getScreenX());
}
} else {
if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
setStageWidth(mouseEventX + startX);
}
}
}
}
}
}
private void setStageWidth(double width) {
width = Math.min(width, maxWidth);
width = Math.max(width, minWidth);
stage.setWidth(width);
}
private void setStageHeight(double height) {
height = Math.min(height, maxHeight);
height = Math.max(height, minHeight);
stage.setHeight(height);
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是 @Alexander.Berg 的帖子的修订版。这可以正确处理场景的 minWidth 和 maxWidth 属性。他的版本没有这样做:它完全忽略了 maxWidth 和屠夫 minWidth。底部还有一段代码允许拖动窗口。
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;
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);
}
}
private 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);
}
}
}
private 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;
private double startScreenX = 0;
private double startScreenY = 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();
double mouseEventY = mouseEvent.getSceneY();
double sceneWidth = scene.getWidth();
double sceneHeight = scene.getHeight();
if (MouseEvent.MOUSE_MOVED.equals(mouseEventType)) {
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)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
if (!Cursor.DEFAULT.equals(cursorEvent)) {
if (!Cursor.W_RESIZE.equals(cursorEvent) && !Cursor.E_RESIZE.equals(cursorEvent)) {
double minHeight = stage.getMinHeight() > (border * 2) ? stage.getMinHeight() : (border * 2);
double maxHeight = stage.getMaxHeight();
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.N_RESIZE.equals(cursorEvent) || Cursor.NE_RESIZE.equals(cursorEvent)) {
double newHeight = stage.getHeight() - (mouseEvent.getScreenY() - stage.getY());
if (newHeight >= minHeight && newHeight <= maxHeight) {
stage.setHeight(newHeight);
stage.setY(mouseEvent.getScreenY());
} else {
newHeight = Math.min(Math.max(newHeight, minHeight), maxHeight);
// y1 + h1 = y2 + h2
// y1 = y2 + h2 - h1
stage.setY(stage.getY() + stage.getHeight() - newHeight);
stage.setHeight(newHeight);
}
} else {
stage.setHeight(Math.min(Math.max(mouseEventY + startY, minHeight), maxHeight));
}
}
if (!Cursor.N_RESIZE.equals(cursorEvent) && !Cursor.S_RESIZE.equals(cursorEvent)) {
double minWidth = stage.getMinWidth() > (border * 2) ? stage.getMinWidth() : (border * 2);
double maxWidth = stage.getMaxWidth();
if (Cursor.NW_RESIZE.equals(cursorEvent) || Cursor.W_RESIZE.equals(cursorEvent) || Cursor.SW_RESIZE.equals(cursorEvent)) {
double newWidth = stage.getWidth() - (mouseEvent.getScreenX() - stage.getX());
if (newWidth >= minWidth && newWidth <= maxWidth) {
stage.setWidth(newWidth);
stage.setX(mouseEvent.getScreenX());
} else {
newWidth = Math.min(Math.max(newWidth, minWidth), maxWidth);
// x1 + w1 = x2 + w2
// x1 = x2 + w2 - w1
stage.setX(stage.getX() + stage.getWidth() - newWidth);
stage.setWidth(newWidth);
}
} else {
stage.setWidth(Math.min(Math.max(mouseEventX + startX, minWidth), maxWidth));
}
}
}
}
if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType)) {
startScreenX = mouseEvent.getScreenX();
startScreenY = mouseEvent.getScreenY();
} else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
if (Cursor.DEFAULT.equals(cursorEvent)) {
stage.setX(stage.getX() + mouseEvent.getScreenX() - startScreenX);
startScreenX = mouseEvent.getScreenX();
stage.setY(stage.getY() + mouseEvent.getScreenY() - startScreenY);
startScreenY = mouseEvent.getScreenY();
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8339 次 |
| 最近记录: |