我正在制作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");
}
}
图像:
答案 0 :(得分:32)
我创建了一个ResizeHelper类,在这种情况下可以帮助你,用法:
ResizeHelper.addResizeListener(yourStage);
助手类:
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);
}
}
}
}
}
}
}
}
答案 1 :(得分:3)
以下是@ 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);
}
}
}
答案 2 :(得分:2)
我更新了@ Yevhenii.Kanivets的@ Alexander.Berg的ResizeHelper类的更新版本。这包括拖动场景的能力,以及我发现的ResizeHelper的最佳实现。还要将最小舞台大小设置为1的高度和1的宽度,而不是0,因为如果它们停留在0,则存在错误。
仍然有人可以改善这个答案。尽管这是个小问题,但SW,W,NW,N和NE边缘的大小调整不平滑。从这些边缘调整大小时,场景也可能会稍微移动。它们应像S,SE和E边缘一样平滑地调整大小。后面的边缘不会移动场景。
我不能代表@ M.K的实现,因为我没有使用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);
}
}
}
答案 3 :(得分:1)
这是@ 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();
}
}
}
}
}
答案 4 :(得分:0)
在我尝试“解决”它之前,我已经研究了一些讨论它的线程,但最终没有问题。
我在右下角创建了一个按钮,给Button一个OnDraggedMethod并简单地使用了mouseevent并在MousePosition上设置了Height / Width - 阶段X / Y位置。
double newX = event.getScreenX() - stage.getX() + 13;
double newY = event.getScreenY() - stage.getY() + 10;
if (newX % 5 == 0 || newY % 5 == 0) {
if (newX > 550) {
stage.setWidth(newX);
} else {
stage.setWidth(550);
}
if (newY > 200) {
stage.setHeight(newY);
} else {
stage.setHeight(200);
}
}
另外,我设置了最小宽度和高度。 并且因为我认为滞后调整动画很烦人我用if包围声明并且每隔5个像素调整一次舞台。
看起来好多了!
PS:+13和+10仅适用于MousePosition。其他鼠标是在角落而不是按钮^^。
答案 5 :(得分:0)
我能说什么......我是一个学习缓慢的人。我花了一些时间来仔细阅读所有代码并理解它。它并不难......只是发生了很多事情。我决定进行一些更改以使用绝对鼠标位置而不是相对鼠标位置,我还改变了整体类使用静态成员和诸如此类的东西。这就是我想出来的,对我自己来说效果很好。对于那些寻找类似解决方案的人,请享受我丰富的评论......使用此类的此类版本非常简单:
ResizeListener listener = new ResizeListener(stage);
NVL2( string1, value_if_not_null, value_if_null )
答案 6 :(得分:0)
以下是 @ Alexander.Berg 发布的ResizeHelper的更新版本,它支持窗口拖动:
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 {
private static double xOffset = 0;
private static double yOffset = 0;
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;
xOffset = mouseEvent.getSceneX();
yOffset = mouseEvent.getSceneY();
} 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);
}
}
}
}
else if (mouseEvent.getSceneY() < 70) {
stage.setX(mouseEvent.getScreenX() - xOffset);
stage.setY(mouseEvent.getScreenY() - yOffset);
}
}
}
}
}
答案 7 :(得分:0)
Thanks @Alexander.Berg for providing this utility class (1st version). It helped me to get the desired functionality for my Undecorated Stage.
However, I have few queries regarding some points:
I tried to modify your code to address all the above queries. Please find below the updated ResizeHelper. I am only trying to simplify the things a bit further. Once again thanks for providing the code and letting me to think with a starting point.
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
/**
* Helper class to set the resizing implementation for any given undecorated stage.
*/
public class ResizeHelper {
/**
* Handler to process the resizing of the the given stage.
*/
static class ResizeHandler implements EventHandler<MouseEvent> {
/** Space to consider around the stage border for resizing */
private static final int BORDER = 10;
/** Stage to which the handler is implemented */
private final Stage stage;
/** Current cursor reference to the scene */
private Cursor cursor = Cursor.DEFAULT;
/** X position of the drag start */
private double startX = 0;
/** Y position of the drag start */
private double startY = 0;
/**
* Constructor.
*
* @param stageTmp Stage to which resizing to be set.
*/
public ResizeHandler(final Stage stageTmp) {
stage = stageTmp;
}
@Override
public void handle(final MouseEvent event) {
final EventType<? extends MouseEvent> eventType = event.getEventType();
final Scene scene = stage.getScene();
final double mouseEventX = event.getSceneX();
final double mouseEventY = event.getSceneY();
final double sceneWidth = scene.getWidth();
final double sceneHeight = scene.getHeight();
if (MouseEvent.MOUSE_MOVED.equals(eventType)) {
setCursor(mouseEventX, mouseEventY, sceneWidth, sceneHeight);
scene.setCursor(cursor);
} else if (MouseEvent.MOUSE_PRESSED.equals(eventType)) {
startX = stage.getWidth() - mouseEventX;
startY = stage.getHeight() - mouseEventY;
consumeEventIfNotDefaultCursor(event);
} else if (MouseEvent.MOUSE_DRAGGED.equals(eventType) && !Cursor.DEFAULT.equals(cursor)) {
consumeEventIfNotDefaultCursor(event);
if (!Cursor.W_RESIZE.equals(cursor) && !Cursor.E_RESIZE.equals(cursor)) {
processVerticalDrag(event);
}
if (!Cursor.N_RESIZE.equals(cursor) && !Cursor.S_RESIZE.equals(cursor)) {
processHorizontalDrag(event);
}
}
}
/**
* Consumes the mouse event if the cursor is not the DEFAULT cursor.
*
* @param event MouseEvent instance.
*/
private void consumeEventIfNotDefaultCursor(final MouseEvent event) {
if (!cursor.equals(Cursor.DEFAULT)) {
event.consume();
}
}
/**
* Processes the horizontal drag movement and resizes the window width.
*
* @param event MouseEvent instance.
*/
private void processHorizontalDrag(final MouseEvent event) {
final double minWidth =
stage.getMinWidth() > BORDER * 2 ? stage.getMinWidth() : BORDER * 2;
final double mouseEventX = event.getSceneX();
if (Cursor.NW_RESIZE.equals(cursor)
|| Cursor.W_RESIZE.equals(cursor)
|| Cursor.SW_RESIZE.equals(cursor)) {
if (stage.getWidth() > minWidth || mouseEventX < 0) {
stage.setWidth(stage.getX() - event.getScreenX() + stage.getWidth());
stage.setX(event.getScreenX());
}
} else if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
stage.setWidth(mouseEventX + startX);
}
}
/**
* Processes the vertical drag movement and resizes the window height.
*
* @param event MouseEvent instance.
*/
private void processVerticalDrag(final MouseEvent event) {
final double minHeight =
stage.getMinHeight() > BORDER * 2 ? stage.getMinHeight() : BORDER * 2;
final double mouseEventY = event.getSceneY();
if (Cursor.NW_RESIZE.equals(cursor)
|| Cursor.N_RESIZE.equals(cursor)
|| Cursor.NE_RESIZE.equals(cursor)) {
if (stage.getHeight() > minHeight || mouseEventY < 0) {
stage.setHeight(stage.getY() - event.getScreenY() + stage.getHeight());
stage.setY(event.getScreenY());
}
} else if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
stage.setHeight(mouseEventY + startY);
}
}
/**
* Determines and sets the appropriate cursor based on the mouse position in relative to scene bounds.
*
* @param mouseEventX X position of mouse in the scene.
* @param mouseEventY Y position of mouse in the scene.
* @param sceneWidth Width of the scene.
* @param sceneHeight Height of the scene.
*/
private void setCursor(final double mouseEventX, final double mouseEventY, final double sceneWidth,
final double sceneHeight) {
final Cursor cursor1;
if (mouseEventX < BORDER && mouseEventY < BORDER) {
cursor1 = Cursor.NW_RESIZE;
} else if (mouseEventX < BORDER && mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.SW_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER && mouseEventY < BORDER) {
cursor1 = Cursor.NE_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER && mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.SE_RESIZE;
} else if (mouseEventX < BORDER) {
cursor1 = Cursor.W_RESIZE;
} else if (mouseEventX > sceneWidth - BORDER) {
cursor1 = Cursor.E_RESIZE;
} else if (mouseEventY < BORDER) {
cursor1 = Cursor.N_RESIZE;
} else if (mouseEventY > sceneHeight - BORDER) {
cursor1 = Cursor.S_RESIZE;
} else {
cursor1 = Cursor.DEFAULT;
}
cursor = cursor1;
}
}
/**
* Constructor.
*
*/
private ResizeHelper() {
}
/**
* Adds the resize handler to the provided stage.
*
* @param stage Stage to which the resizing should be implemented.
*/
public static void addResizeHandler(final Stage stage) {
ResizeHandler resizeHandler = new ResizeHandler(stage);
stage.setMinHeight(stage.getHeight());
stage.setMinWidth(stage.getWidth());
stage.setMaxHeight(stage.getMaxHeight());
stage.setMaxWidth(stage.getMaxWidth());
stage.getScene().addEventFilter(MouseEvent.ANY, resizeHandler);
}
}
答案 8 :(得分:0)
受此处众多答案的启发,我编写了自己的实现,该实现具有我能想到的所有必要功能:
可拖动性
全屏
可调整大小
快速设置:
StageInteractor(this)
.makeDraggable()
.makeFullscreenable()
.makeResizable()
自定义交互区域:
StageInteractor(this)
// custom width / height for drag areas (top, right, bottom, left)
.makeDraggable(50, 20, 50, 20)
// custom width / height for double-clickable areas (top, right, bottom, left)
.makeFullscreenable(50, 20, 50, 20)
// custom width / height for resize areas (top, right, bottom, left)
.makeResizable(20, 20, 20, 20)
import javafx.scene.Cursor
import javafx.scene.Scene
import javafx.scene.input.MouseButton
import javafx.scene.input.MouseEvent
import javafx.stage.Screen
import javafx.stage.Stage
class StageInteractor {
private val stage: Stage
private val scene: Scene
private var isDraggable = false
private var isDragging = false
private var allowDragging = true
private var dragMarginTop = 0.0
private var dragMarginRight = 0.0
private var dragMarginBottom = 0.0
private var dragMarginLeft = 0.0
private var isFullscreenable = false
private var isFullscreen = false
private var allowFullscreen = true
private var fullscreenMarginTop = 0.0
private var fullscreenMarginRight = 0.0
private var fullscreenMarginBottom = 0.0
private var fullscreenMarginLeft = 0.0
private var stageWidthBeforeFullscreen = 0.0
private var stageHeightBeforeFullscreen = 0.0
private var stageXBeforeFullscreen = 0.0
private var stageYBeforeFullscreen = 0.0
private var isResizeable = false
private var isResizing = false
private var allowResizing = true
private var resizeDirection: ResizeDirection? = null
private var resizeMarginTop = 0.0
private var resizeMarginRight = 0.0
private var resizeMarginBottom = 0.0
private var resizeMarginLeft = 0.0
constructor(stage: Stage) {
this.stage = stage
this.scene = stage.scene
}
fun makeDraggable(
marginTop: Double = 50.0,
marginRight: Double = 0.0,
marginBottom: Double = 0.0,
marginLeft: Double = 0.0
): StageInteractor {
dragMarginTop = marginTop
dragMarginRight = marginRight
dragMarginBottom = marginBottom
dragMarginLeft = marginLeft
if (!isDraggable) {
isDraggable = true
var dragStartOffsetX = 0.0
var dragStartOffsetY = 0.0
scene.addEventHandler(MouseEvent.MOUSE_MOVED) {
val isWithinBounds = detectDraggingBounds(it)
if (isDraggable && allowDragging && isWithinBounds) {
scene.cursor = Cursor.OPEN_HAND
} else {
if (scene.cursor == Cursor.OPEN_HAND) {
scene.cursor = Cursor.DEFAULT
}
}
}
scene.addEventHandler(MouseEvent.MOUSE_PRESSED) {
dragStartOffsetX = stage.x - it.screenX
dragStartOffsetY = stage.y - it.screenY
}
scene.addEventHandler(MouseEvent.MOUSE_DRAGGED) {
val isWithinBounds = detectDraggingBounds(it)
if (isDraggable && allowDragging && isWithinBounds) {
isDragging = true
scene.cursor = Cursor.CLOSED_HAND
}
if (isDragging) {
stage.x = it.screenX + dragStartOffsetX
stage.y = it.screenY + dragStartOffsetY
}
}
scene.addEventHandler(MouseEvent.MOUSE_RELEASED) {
if (isDragging) {
isDragging = false
scene.cursor = Cursor.DEFAULT
}
}
}
return this
}
private fun detectDraggingBounds(event: MouseEvent): Boolean {
return event.sceneY <= dragMarginTop
|| scene.height - event.sceneY <= dragMarginBottom
|| event.sceneX <= dragMarginLeft
|| scene.width - event.sceneX <= dragMarginRight
}
fun makeFullscreenable(
marginTop: Double = 50.0,
marginRight: Double = 0.0,
marginBottom: Double = 0.0,
marginLeft: Double = 0.0
): StageInteractor {
fullscreenMarginTop = marginTop
fullscreenMarginRight = marginRight
fullscreenMarginBottom = marginBottom
fullscreenMarginLeft = marginLeft
if (!isFullscreenable) {
isFullscreenable = true
scene.addEventHandler(MouseEvent.MOUSE_PRESSED) {
val isDoubleClick = it.button == MouseButton.PRIMARY && it.clickCount >= 2
if (isFullscreenable && allowFullscreen && isDoubleClick && detectFullscreenBounds(it)) {
if (isFullscreen) {
isFullscreen = false
allowDragging = true
allowResizing = true
stage.x = stageXBeforeFullscreen
stage.y = stageYBeforeFullscreen
stage.width = stageWidthBeforeFullscreen
stage.height = stageHeightBeforeFullscreen
} else {
isFullscreen = true
allowDragging = false
allowResizing = false
stageWidthBeforeFullscreen = stage.width
stageHeightBeforeFullscreen = stage.height
stageXBeforeFullscreen = stage.x
stageYBeforeFullscreen = stage.y
val screenBounds = Screen.getPrimary().visualBounds
val newWidth = if (stage.maxWidth < screenBounds.width) {
stage.maxWidth
} else {
screenBounds.width
}
val newHeight = if (stage.maxHeight < screenBounds.height) {
stage.maxHeight
} else {
screenBounds.height
}
stage.width = newWidth
stage.height = newHeight
stage.x = screenBounds.minX
stage.y = screenBounds.minY
}
}
}
}
return this
}
private fun detectFullscreenBounds(event: MouseEvent): Boolean {
val isWithinBounds = event.sceneY <= fullscreenMarginTop
|| scene.height - event.sceneY <= fullscreenMarginBottom
|| event.sceneX <= fullscreenMarginLeft
|| scene.width - event.sceneX <= fullscreenMarginRight
val resizeDirection = detectResizeDirection(event)
return isWithinBounds && resizeDirection == null
}
fun makeResizable(
marginTop: Double = 10.0,
marginRight: Double = 10.0,
marginBottom: Double = 10.0,
marginLeft: Double = 10.0
): StageInteractor {
resizeMarginTop = marginTop
resizeMarginRight = marginRight
resizeMarginBottom = marginBottom
resizeMarginLeft = marginLeft
if (!isResizeable) {
isResizeable = true
scene.addEventHandler(MouseEvent.MOUSE_MOVED) {
if (isResizeable && allowResizing && !isResizing) {
when (detectResizeDirection(it)) {
ResizeDirection.NORTH_WEST -> scene.cursor = Cursor.NW_RESIZE
ResizeDirection.NORTH_EAST -> scene.cursor = Cursor.NE_RESIZE
ResizeDirection.SOUTH_WEST -> scene.cursor = Cursor.SW_RESIZE
ResizeDirection.SOUTH_EAST -> scene.cursor = Cursor.SE_RESIZE
ResizeDirection.NORTH -> scene.cursor = Cursor.N_RESIZE
ResizeDirection.SOUTH -> scene.cursor = Cursor.S_RESIZE
ResizeDirection.WEST -> scene.cursor = Cursor.W_RESIZE
ResizeDirection.EAST -> scene.cursor = Cursor.E_RESIZE
else -> {
val cursors = listOf(
Cursor.NW_RESIZE,
Cursor.NE_RESIZE,
Cursor.SW_RESIZE,
Cursor.SE_RESIZE,
Cursor.N_RESIZE,
Cursor.S_RESIZE,
Cursor.W_RESIZE,
Cursor.E_RESIZE
)
if (cursors.contains(scene.cursor)) {
scene.cursor = Cursor.DEFAULT
}
}
}
}
}
var resizeStartFromSceneX = 0.0
var resizeStartFromSceneY = 0.0
var resizeStartFromScreenX = 0.0
var resizeStartFromScreenY = 0.0
var resizeStartStageWidth = 0.0
var resizeStartStageHeight = 0.0
scene.addEventHandler(MouseEvent.MOUSE_PRESSED) {
if (isResizeable && allowResizing && !isResizing) {
resizeDirection = detectResizeDirection(it)
if (resizeDirection != null) {
if (it.button == MouseButton.PRIMARY && it.clickCount >= 2) {
val screenBounds = Screen.getPrimary().visualBounds
if (resizeDirection == ResizeDirection.NORTH || resizeDirection == ResizeDirection.NORTH_WEST || resizeDirection == ResizeDirection.NORTH_EAST) {
stage.height = ensureStageHeightIsWithinLimits(
stage.height + stage.y - screenBounds.minY
)
stage.y = 0.0
}
if (resizeDirection == ResizeDirection.SOUTH || resizeDirection == ResizeDirection.SOUTH_WEST || resizeDirection == ResizeDirection.SOUTH_EAST) {
stage.height = ensureStageHeightIsWithinLimits(
screenBounds.height - stage.y + screenBounds.minY
)
if (stage.height == screenBounds.height) {
stage.y = 0.0
}
}
if (resizeDirection == ResizeDirection.WEST || resizeDirection == ResizeDirection.NORTH_WEST || resizeDirection == ResizeDirection.SOUTH_WEST) {
stage.width = ensureStageWidthIsWithinLimits(
stage.width + stage.x
)
stage.x = 0.0
}
if (resizeDirection == ResizeDirection.EAST || resizeDirection == ResizeDirection.NORTH_EAST || resizeDirection == ResizeDirection.SOUTH_EAST) {
stage.width = ensureStageWidthIsWithinLimits(
screenBounds.width - stage.x
)
if (stage.width == screenBounds.width) {
stage.x = 0.0
}
}
} else {
isResizing = true
isDraggable = false
isFullscreenable = false
resizeStartFromScreenX = it.screenX
resizeStartFromScreenY = it.screenY
resizeStartFromSceneX = it.sceneX
resizeStartFromSceneY = it.sceneY
resizeStartStageWidth = stage.width
resizeStartStageHeight = stage.height
}
}
}
}
scene.addEventHandler(MouseEvent.MOUSE_DRAGGED) {
if (isResizing) {
if (resizeDirection == ResizeDirection.NORTH || resizeDirection == ResizeDirection.NORTH_WEST || resizeDirection == ResizeDirection.NORTH_EAST) {
val newHeight = ensureStageHeightIsWithinLimits(
resizeStartStageHeight + (resizeStartFromScreenY - it.screenY)
)
val newY = when (newHeight) {
stage.maxHeight, stage.minHeight -> stage.y
else -> it.screenY - resizeStartFromSceneY
}
stage.height = newHeight
stage.y = newY
}
if (resizeDirection == ResizeDirection.SOUTH || resizeDirection == ResizeDirection.SOUTH_WEST || resizeDirection == ResizeDirection.SOUTH_EAST) {
val newHeight = ensureStageHeightIsWithinLimits(
resizeStartStageHeight + (it.screenY - resizeStartFromScreenY)
)
stage.height = newHeight
}
if (resizeDirection == ResizeDirection.WEST || resizeDirection == ResizeDirection.NORTH_WEST || resizeDirection == ResizeDirection.SOUTH_WEST) {
val newWidth = ensureStageWidthIsWithinLimits(
resizeStartStageWidth + (resizeStartFromScreenX - it.screenX)
)
val newX = when (newWidth) {
stage.maxWidth, stage.minWidth -> stage.x
else -> it.screenX - resizeStartFromSceneX
}
stage.width = newWidth
stage.x = newX
}
if (resizeDirection == ResizeDirection.EAST || resizeDirection == ResizeDirection.NORTH_EAST || resizeDirection == ResizeDirection.SOUTH_EAST) {
val newWidth = ensureStageWidthIsWithinLimits(
resizeStartStageWidth + (it.screenX - resizeStartFromScreenX)
)
stage.width = newWidth
}
}
}
scene.addEventHandler(MouseEvent.MOUSE_RELEASED) {
if (isResizing) {
isResizing = false
isDraggable = true
isFullscreenable = true
}
}
}
return this
}
private fun detectResizeDirection(event: MouseEvent): ResizeDirection? {
val isNorthResize = event.sceneY <= resizeMarginTop
val isSouthResize = scene.height - event.sceneY <= resizeMarginBottom
val isWestResize = event.sceneX <= resizeMarginLeft
val isEastResize = scene.width - event.sceneX <= resizeMarginRight
val isNorthWestResize = isNorthResize && isWestResize
val isNorthEastResize = isNorthResize && isEastResize
val isSouthWestResize = isSouthResize && isWestResize
val isSouthEastResize = isSouthResize && isEastResize
return when {
isNorthWestResize -> ResizeDirection.NORTH_WEST
isNorthEastResize -> ResizeDirection.NORTH_EAST
isSouthWestResize -> ResizeDirection.SOUTH_WEST
isSouthEastResize -> ResizeDirection.SOUTH_EAST
isNorthResize -> ResizeDirection.NORTH
isSouthResize -> ResizeDirection.SOUTH
isWestResize -> ResizeDirection.WEST
isEastResize -> ResizeDirection.EAST
else -> null
}
}
private fun ensureStageWidthIsWithinLimits(width: Double): Double {
val screenBounds = Screen.getPrimary().visualBounds
return when {
width > stage.maxWidth -> stage.maxWidth
width < stage.minWidth -> stage.minWidth
width > screenBounds.width -> screenBounds.width
else -> width
}
}
private fun ensureStageHeightIsWithinLimits(height: Double): Double {
val screenBounds = Screen.getPrimary().visualBounds
return when {
height > stage.maxHeight -> stage.maxHeight
height < stage.minHeight -> stage.minHeight
height > screenBounds.height -> screenBounds.height
else -> height
}
}
enum class ResizeDirection {
NORTH, NORTH_EAST, NORTH_WEST,
SOUTH, SOUTH_EAST, SOUTH_WEST,
EAST, WEST;
}
}
答案 9 :(得分:0)
我在舞台的根容器中也使原始解决方案也支持填充。否则,光标将无法正确设置,并且大小也将无法调整。 通过在开始拖动时考虑到鼠标在舞台内的位置,避免在舞台重新定位时避免“跳” ,调整大小的效果也更好。
package apro2.canbustool.ui.util;
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Insets;
import javafx.scene.Cursor;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.stage.Stage;
//created by Alexander Berg
public class ResizeHelper {
public static ResizeListener addResizeListener (Stage stage) {
ResizeListener resizeListener = new ResizeListener(stage);
Scene scene = stage.getScene();
scene.addEventHandler(MouseEvent.MOUSE_MOVED, resizeListener);
scene.addEventHandler(MouseEvent.MOUSE_PRESSED, resizeListener);
scene.addEventHandler(MouseEvent.MOUSE_DRAGGED, resizeListener);
scene.addEventHandler(MouseEvent.MOUSE_EXITED, resizeListener);
scene.addEventHandler(MouseEvent.MOUSE_EXITED_TARGET, resizeListener);
return resizeListener;
}
public static class ResizeListener implements EventHandler<MouseEvent> {
private Stage stage;
private Scene scene;
private Cursor cursorEvent = Cursor.DEFAULT;
private int border = 4;
private double startX = 0;
private double startY = 0;
private double sceneOffsetX = 0;
private double sceneOffsetY = 0;
private double padTop = 0;
private double padRight = 0;
private double padBottom = 0;
private double padLeft = 0;
public ResizeListener (Stage stage) {
this.stage = stage;
this.scene = stage.getScene();
}
public void setPadding (Insets padding) {
padTop = padding.getTop();
padRight = padding.getRight();
padBottom = padding.getBottom();
padLeft = padding.getLeft();
}
@Override
public void handle(MouseEvent mouseEvent) {
EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType();
double mouseEventX = mouseEvent.getSceneX(),
mouseEventY = mouseEvent.getSceneY(),
viewWidth = stage.getWidth() - padLeft - padRight,
viewHeight = stage.getHeight() - padTop - padBottom;
if (MouseEvent.MOUSE_MOVED.equals(mouseEventType)) {
if (mouseEventX < border + padLeft && mouseEventY < border + padTop) {
cursorEvent = Cursor.NW_RESIZE;
}
else if (mouseEventX < border + padLeft && mouseEventY > viewHeight - border + padTop) {
cursorEvent = Cursor.SW_RESIZE;
}
else if (mouseEventX > viewWidth - border + padLeft && mouseEventY < border + padTop) {
cursorEvent = Cursor.NE_RESIZE;
}
else if (mouseEventX > viewWidth - border + padLeft && mouseEventY > viewHeight - border + padTop) {
cursorEvent = Cursor.SE_RESIZE;
}
else if (mouseEventX < border + padLeft) {
cursorEvent = Cursor.W_RESIZE;
}
else if (mouseEventX > viewWidth - border + padLeft) {
cursorEvent = Cursor.E_RESIZE;
}
else if (mouseEventY < border + padTop) {
cursorEvent = Cursor.N_RESIZE;
}
else if (mouseEventY > viewHeight - border + padTop) {
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 = viewWidth - mouseEventX;
startY = viewHeight - mouseEventY;
sceneOffsetX = mouseEvent.getSceneX();
sceneOffsetY = mouseEvent.getSceneY();
}
else if (MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) && !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) {
double height = stage.getY() - mouseEvent.getScreenY() + stage.getHeight() + sceneOffsetY;
double y = mouseEvent.getScreenY() - sceneOffsetY;
stage.setHeight(height);
stage.setY(y);
}
} else {
if (stage.getHeight() > minHeight || mouseEventY + startY - stage.getHeight() > 0) {
stage.setHeight(mouseEventY + startY + padBottom + padTop);
}
}
}
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) {
double width = stage.getX() - mouseEvent.getScreenX() + stage.getWidth() + sceneOffsetX;
double x = mouseEvent.getScreenX() - sceneOffsetX;
stage.setWidth(width);
stage.setX(x);
}
} else {
if (stage.getWidth() > minWidth || mouseEventX + startX - stage.getWidth() > 0) {
stage.setWidth(mouseEventX + startX + padLeft + padRight);
}
}
}
}
}
}
}
答案 10 :(得分:0)
我知道这个线程很旧,但是我认为新人们正在为这个问题而绊脚石,上面提供的代码没有使真正的方法成为可能,我花了大约2天的时间使用上面的解决方案,并且不希望有完美的可拖动和可调整大小的窗口,直到现在。
https://github.com/goxr3plus/FX-BorderlessScene
该库使用3行代码设法使场景表现出了正确的行为,从而节省了我的理智。
答案 11 :(得分:0)
支持:
构建概念:
使用 Alignment.TOP|RIGHT|BOTTOM|LEFT
和 Alignment.TOP_LEFT|BOTTOM_LEFT
作为角将边框调整大小窗格放置在根 StackPane 内
Gluon GUI 设计器 FXML_Structure:
/** Copyright © 2021 Izon Company, Free To Share: class ResizeHelper.java */
import javafx.event.EventHandler;
import javafx.event.EventType;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.stage.Screen;
import javafx.stage.Stage;
/**
* handles Stage resizing for StageStyle.UNDECORATED and deals with a
* indentation which can be used to render a CSS drop shadow effect around the
* scene with transparent background.
*
* @author Henryk Zschuppan,
* @date MARCH 01,21
*/
public class ResizeHandler implements EventHandler<MouseEvent> {
public static ResizeHandler install(Stage stage, double titlebarHeight, double pullEdgeDepth, double indentation) {
ResizeHandler handler = new ResizeHandler(stage, titlebarHeight, pullEdgeDepth, indentation);
stage.getScene().addEventHandler(MouseEvent.ANY, handler);
return handler;
}
public static Rectangle2D SCREEN_BOUNDS = Screen.getPrimary().getVisualBounds();
/** select the boundary clipping orientation in relation to the stage */
private static enum CHECK {
LOW,
HIGH,
NONE;
}
/** Stage to which the handler is implemented */
final private Stage stage;
/** Area from top to consider for stage reposition */
double titlebarHeight;
/** Space to consider around the stage border for resizing */
final private int depth;
/** padding space to render in the CSS effect drop shadow */
final private double pad;
/** stage size limits */
final private double minWidth, minHeight, maxWidth, maxHeight;
/** start point of mouse position on screen */
private Point2D startDrag = null;
/** frame rectangle of the stage on drag start */
private Rectangle2D startRectangle;
/** the relative mouse orientation to the stage */
private CHECK checkX = CHECK.NONE, checkY = CHECK.NONE;
private boolean inRepositioningArea = false;
private ResizeHandler(Stage stage, double titlebarHeight, double pullEdgeDepth, double indentation) {
this.stage = stage;
this.titlebarHeight = titlebarHeight;
pad = indentation;
depth = (int) (indentation + pullEdgeDepth);
minWidth = stage.getMinWidth();
minHeight = stage.getMinHeight();
maxWidth = stage.getMaxWidth();
maxHeight = stage.getMaxHeight();
}
@Override
public void handle(MouseEvent mouseEvent) {
if (!mouseEvent.getButton().equals(MouseButton.PRIMARY))
return;
EventType<? extends MouseEvent> mouseEventType = mouseEvent.getEventType();
final double mX = mouseEvent.getScreenX();
final double mY = mouseEvent.getScreenY();
/* local coordinates inside stage */
final double lX = mouseEvent.getSceneX();
final double lY = mouseEvent.getSceneY();
final double sW = stage.getWidth();
final double sH = stage.getHeight();
if (MouseEvent.MOUSE_PRESSED.equals(mouseEventType)) {
if (lX < depth && lY < depth) {
setXYCheck(CHECK.LOW, CHECK.LOW);
} else if (lX < depth && lY > sH - depth) {
setXYCheck(CHECK.LOW, CHECK.HIGH);
} else if (lX > sW - depth && lY < depth) {
setXYCheck(CHECK.HIGH, CHECK.LOW);
} else if (lX > sW - depth && lY > sH - depth) {
setXYCheck(CHECK.HIGH, CHECK.HIGH);
} else if (lX < depth) {
setXYCheck(CHECK.LOW, CHECK.NONE);
} else if (lX > sW - depth) {
setXYCheck(CHECK.HIGH, CHECK.NONE);
} else if (lY < depth) {
setXYCheck(CHECK.NONE, CHECK.LOW);
} else if (lY > sH - depth) {
setXYCheck(CHECK.NONE, CHECK.HIGH);
} else {
setXYCheck(CHECK.NONE, CHECK.NONE);
}
/* check mouse is not inside the resize border space */
if (lX < pad || lY < pad || lX > sW - pad || lY > sH - pad) {
setXYCheck(CHECK.NONE, CHECK.NONE);
}
inRepositioningArea = lY >= depth && lY < this.titlebarHeight + pad;
startDrag = new Point2D(mX, mY);
startRectangle = new Rectangle2D(stage.getX(), stage.getY(), sW, sH);
} else if (!isNone() && MouseEvent.MOUSE_DRAGGED.equals(mouseEventType)) {
/* stage resizing */
double dX = mX - startDrag.getX();
double dY = mY - startDrag.getY();
double min, max;
/* don't overwrite start values */
double x = startRectangle.getMinX(), y = startRectangle.getMinY(), x2 = startRectangle.getMaxX(), y2 = startRectangle.getMaxY();
switch (checkX) {
case LOW :// LEFT
min = Math.max(x - maxWidth, (0 - pad));
max = x2 - minWidth;
x = clip(x + dX, min, max);
break;
case HIGH : // RIGHT
min = x + minWidth;
max = Math.min(x + maxWidth, SCREEN_BOUNDS.getWidth() + pad);
x2 = clip(x2 + dX, min, max);
default :
break;
}
switch (checkY) {
case LOW : // TOP
min = Math.max(y2 - maxHeight, (0 - pad));
max = y2 - minHeight;
y = clip(y + dY, min, max);
break;
case HIGH :// BOTTOM
min = y + minHeight;
max = Math.min(y + maxHeight, SCREEN_BOUNDS.getHeight() + pad);
y2 = clip(y2 + dY, min, max);
default :
break;
}
updateStagePosition(x, y, x2, y2);
} else if (isNone() && MouseEvent.MOUSE_DRAGGED.equals(mouseEventType) && inRepositioningArea) {
/* stage repositioning */
double dX = mX - startDrag.getX();
double dY = mY - startDrag.getY();
this.stage.setX(startRectangle.getMinX() + dX);
this.stage.setY(startRectangle.getMinY() + dY);
stagePositionInsideScreen();
} else if (!isNone() && MouseEvent.MOUSE_RELEASED.equals(mouseEventType) && mouseEvent.getClickCount() == 2) {
/* The stage side is expanded or minimized by double-clicking */
double min, max;
/* don't overwrite start values */
double x = startRectangle.getMinX(), y = startRectangle.getMinY(), x2 = startRectangle.getMaxX(), y2 = startRectangle.getMaxY();
switch (checkX) {
case LOW :// LEFT
if (x > (0 - pad)) {
min = Math.max(x - maxWidth, (0 - pad));
max = x2 - minWidth;
x = clip((0 - pad), min, max);
} else {
x = x2 - minWidth;
}
break;
case HIGH : // RIGHT
if (x2 < SCREEN_BOUNDS.getWidth() + pad) {
min = x + minWidth;
max = Math.min(x + maxWidth, SCREEN_BOUNDS.getWidth() + pad);
x2 = clip(SCREEN_BOUNDS.getWidth() + pad, min, max);
} else {
x2 = x + minWidth;
}
default :
break;
}
switch (checkY) {
case LOW : // TOP
if (y > (0 - pad)) {
min = Math.max(y2 - maxHeight, (0 - pad));
max = y2 - minHeight;
y = clip((0 - pad), min, max);
} else {
y = y2 - minHeight;
}
break;
case HIGH :// BOTTOM
if (y2 < SCREEN_BOUNDS.getHeight() + pad) {
min = y + minHeight;
max = Math.min(y + maxHeight, SCREEN_BOUNDS.getHeight() + pad);
y2 = clip(SCREEN_BOUNDS.getHeight() + pad, min, max);
} else {
y2 = y + minHeight;
}
default :
break;
}
updateStagePosition(x, y, x2, y2);
}
}
private double clip(double checkValue, double minValue, double maxValue) {
if (checkValue < minValue) {
return minValue;
}
if (checkValue > maxValue) {
return maxValue;
}
return checkValue; // unmodified
}
private void setXYCheck(CHECK X, CHECK Y) {
checkX = X;
checkY = Y;
}
/** @return true if checkX and checkY is set to CHECK.NONE */
private boolean isNone() {
return checkX.equals(CHECK.NONE) && checkY.equals(CHECK.NONE);
}
private void stagePositionInsideScreen() {
int width = (int) this.stage.getWidth();
int height = (int) this.stage.getHeight();
if (stage.getX() + width - pad >= SCREEN_BOUNDS.getWidth()) {
stage.setX(SCREEN_BOUNDS.getWidth() - width + pad);
}
if (stage.getX() + pad < 0.0D) {
stage.setX(0.0D - pad);
}
if (stage.getY() + height - pad >= SCREEN_BOUNDS.getHeight()) {
stage.setY(SCREEN_BOUNDS.getHeight() - height + pad);
}
if (stage.getY() + pad < 0.0D)
stage.setY(0.0D - pad);
}
private void updateStagePosition(double x1, double y1, double x2, double y2) {
stage.setX(x1);
stage.setY(y1);
stage.setWidth(x2 - x1);
stage.setHeight(y2 - y1);
}
} // CLASS END
不要忘记根据舞台调整最小和最大尺寸值:
public void setApplicationContentLayout(AbstractApp app) {
Pane contentLayout= app.getRootLayout();
BorderPane contentBorderPane = (BorderPane) rootStackPane.getChildren().get(0);
try {
contentBorderPane.setCenter(contentLayout);
// 2 is border width
contentBorderPane.setMinWidth(contentLayout.getMinWidth() + 2);
contentBorderPane.setMaxWidth(contentLayout.getMaxWidth() + 2);
// add titlebar height
contentBorderPane.setMinHeight(contentBorderPane.getMinHeight() + contentLayout.getMinHeight() + 2);
contentBorderPane.setMaxHeight(contentBorderPane.getMinHeight() + contentLayout.getMaxHeight() + 2);
stage.setMinWidth(contentBorderPane.getMinWidth() + 4);
stage.setMinHeight(contentBorderPane.getMinHeight() + 4);
stage.setMaxWidth(contentBorderPane.getMaxWidth() + 4);
stage.setMaxHeight(contentBorderPane.getMaxHeight() + 4);
} catch (NullPointerException e) {
System.out.print("error report:\n");
if (contentLayout == null)
System.out.print("WindowFrame:setApplicationContent: null \n");
}
if (stage.isResizable()) {
ResizeHelper.install(stage, 28, 7, 0);
} else {
System.out.println("ResizeHelper not set, stage not resizable.");
}
}
将 CSS 样式添加到边框窗格
.window{
-fx-effect: dropshadow(three-pass-box, rgb(0,0,0,0.95), 2, 0.6, 0, 1);
}
答案 12 :(得分:-4)
Undecorater似乎是唯一的解决方案。