防止对话框离开屏幕
Prevent dialog from going off screen
我有一个很好的 primaryStage。我有一个以 primaryStage 为中心打开的对话框(我通过让对话框的所有者成为 primaryStage
dialog.setInitOwner(primaryStage).
但是,如果 primaryStage 已经靠近屏幕边缘,对话框将离开屏幕。如果所有者靠近屏幕边缘,如何使对话框(其所有者为 primaryStage)不离开屏幕?
我试过这个:
double x = dialog.getX();
double y = dialog.getY();
double w = dialog.getWidth();
double h = dialog.getHeight();
if (x < Main.bounds.getMinX())
{
dialog.setX(Main.bounds.getMinX());
}
if (x + w > Main.bounds.getMaxX())
{
dialog.setX(Main.bounds.getMaxX() - w);
}
if (y < Main.bounds.getMinY())
{
dialog.setY(Main.bounds.getMinY());
}
if (y + h > Main.bounds.getMaxY())
{
dialog.setY(Main.bounds.getMaxY() - h);
}
dialog.showAndWait();
Main.bounds 创建者:
private static Bounds computeAllScreenBounds()
{
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
for (Screen screen : Screen.getScreens())
{
Rectangle2D screenBounds = screen.getVisualBounds();
if (screenBounds.getMinX() < minX)
{
minX = screenBounds.getMinX();
}
if (screenBounds.getMinY() < minY)
{
minY = screenBounds.getMinY();
}
if (screenBounds.getMaxX() > maxX)
{
maxX = screenBounds.getMaxX();
}
if (screenBounds.getMaxY() > maxY)
{
maxY = screenBounds.getMaxY();
}
}
return new BoundingBox(minX, minY, maxX - minX, maxY - minY);
尝试此操作不会改变任何行为。我觉得这是因为 dialog.getX() 函数 returns a NaN ...
}
应要求,举例:
public class Test extends Application
{
@Override
public void start(Stage primaryStage)
{
Bounds bounds = computeAllScreenBounds();
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.setContentText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
alert.initOwner(primaryStage);
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
if (x < bounds.getMinX())
{
alert.setX(bounds.getMinX());
}
if (x + w > bounds.getMaxX())
{
alert.setX(bounds.getMaxX() - w);
}
if (y < bounds.getMinY())
{
alert.setY(bounds.getMinY());
}
if (y + h > bounds.getMaxY())
{
alert.setY(bounds.getMaxY() - h);
}
alert.showAndWait();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
private static Bounds computeAllScreenBounds()
{
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
for (Screen screen : Screen.getScreens())
{
Rectangle2D screenBounds = screen.getVisualBounds();
if (screenBounds.getMinX() < minX)
{
minX = screenBounds.getMinX();
}
if (screenBounds.getMinY() < minY)
{
minY = screenBounds.getMinY();
}
if (screenBounds.getMaxX() > maxX)
{
maxX = screenBounds.getMaxX();
}
if (screenBounds.getMaxY() > maxY)
{
maxY = screenBounds.getMaxY();
}
}
return new BoundingBox(minX, minY, maxX - minX, maxY - minY);
}
}
另一个例子:
public class Test extends Application
{
@Override
public void start(Stage primaryStage)
{
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.setContentText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
alert.initOwner(primaryStage);
alert.setOnShown(new EventHandler<DialogEvent>()
{
@Override
public void handle(DialogEvent event)
{
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
//SHOWS ALL NaN NaN NaN NaN
System.out.println(x + " " + y + " " + w + " " + h);
}
});
alert.showAndWait();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
当您将对话框放置在舞台中央时..只有当舞台也(至少部分地)在您的屏幕之外时,对话框才能在屏幕之外。
请看下面的代码示例..
@Override
public void start(Stage stage) {
Pane pane = new Pane();
Scene scene = new Scene(pane, 800, 500);
Button button = new Button("Alert");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.initOwner(stage);
alert.setOnShown(new EventHandler<DialogEvent>() {
@Override
public void handle(DialogEvent event) {
System.out.println(alert.getOwner().getX());
System.out.println(alert.getOwner().getY());
//Values from screen
int screenMaxX = (int) Screen.getPrimary().getVisualBounds().getMaxX();
int screenMaxY = (int) Screen.getPrimary().getVisualBounds().getMaxY();
//Values from stage
int width = (int) stage.getWidth();
int height = (int) stage.getHeight();
int stageMaxX = (int) stage.getX();
int stageMaxY = (int) stage.getY();
//Maximal values your stage
int paneMaxX = screenMaxX - width;
int paneMaxY = screenMaxY - height;
//Check if the position of your stage is not out of screen
if (stageMaxX > paneMaxX || stageMaxY > paneMaxY) {
//Set stage where ever you want
}
}
});
alert.showAndWait();
}
});
pane.getChildren().add(button);
stage.setScene(scene);
stage.show();
}
当使用 showAndWait 时,警报中 onShown 处理程序的(对我来说出乎意料的)问题是,在调用处理程序时,警报尚未显示且尚未显示 sized/located - 这有点疯狂并且可能被认为是错误。
一种解决方法是监听警报的 showingProperty 并在该监听器中进行任何 size/location 调整。类似的东西(显然只是一个 poc)
alert.showingProperty().addListener((src, ov, nv) -> {
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
// as example just adjust if location top/left is off
// production must cope with bottom/right off as well, obviously
if (x < 0) {
alert.setWidth(w + x);
alert.setY(0);
}
if (y <0) {
alert.setHeight(h + y);
alert.setY(0);
}
});
alert.showAndWait();
仅供参考:我真的认为这是一个错误,所以提交了一个issue让我们看看会发生什么
我有一个很好的 primaryStage。我有一个以 primaryStage 为中心打开的对话框(我通过让对话框的所有者成为 primaryStage
dialog.setInitOwner(primaryStage).
但是,如果 primaryStage 已经靠近屏幕边缘,对话框将离开屏幕。如果所有者靠近屏幕边缘,如何使对话框(其所有者为 primaryStage)不离开屏幕?
我试过这个:
double x = dialog.getX();
double y = dialog.getY();
double w = dialog.getWidth();
double h = dialog.getHeight();
if (x < Main.bounds.getMinX())
{
dialog.setX(Main.bounds.getMinX());
}
if (x + w > Main.bounds.getMaxX())
{
dialog.setX(Main.bounds.getMaxX() - w);
}
if (y < Main.bounds.getMinY())
{
dialog.setY(Main.bounds.getMinY());
}
if (y + h > Main.bounds.getMaxY())
{
dialog.setY(Main.bounds.getMaxY() - h);
}
dialog.showAndWait();
Main.bounds 创建者:
private static Bounds computeAllScreenBounds()
{
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
for (Screen screen : Screen.getScreens())
{
Rectangle2D screenBounds = screen.getVisualBounds();
if (screenBounds.getMinX() < minX)
{
minX = screenBounds.getMinX();
}
if (screenBounds.getMinY() < minY)
{
minY = screenBounds.getMinY();
}
if (screenBounds.getMaxX() > maxX)
{
maxX = screenBounds.getMaxX();
}
if (screenBounds.getMaxY() > maxY)
{
maxY = screenBounds.getMaxY();
}
}
return new BoundingBox(minX, minY, maxX - minX, maxY - minY);
尝试此操作不会改变任何行为。我觉得这是因为 dialog.getX() 函数 returns a NaN ... }
应要求,举例:
public class Test extends Application
{
@Override
public void start(Stage primaryStage)
{
Bounds bounds = computeAllScreenBounds();
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.setContentText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
alert.initOwner(primaryStage);
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
if (x < bounds.getMinX())
{
alert.setX(bounds.getMinX());
}
if (x + w > bounds.getMaxX())
{
alert.setX(bounds.getMaxX() - w);
}
if (y < bounds.getMinY())
{
alert.setY(bounds.getMinY());
}
if (y + h > bounds.getMaxY())
{
alert.setY(bounds.getMaxY() - h);
}
alert.showAndWait();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
private static Bounds computeAllScreenBounds()
{
double minX = Double.POSITIVE_INFINITY;
double minY = Double.POSITIVE_INFINITY;
double maxX = Double.NEGATIVE_INFINITY;
double maxY = Double.NEGATIVE_INFINITY;
for (Screen screen : Screen.getScreens())
{
Rectangle2D screenBounds = screen.getVisualBounds();
if (screenBounds.getMinX() < minX)
{
minX = screenBounds.getMinX();
}
if (screenBounds.getMinY() < minY)
{
minY = screenBounds.getMinY();
}
if (screenBounds.getMaxX() > maxX)
{
maxX = screenBounds.getMaxX();
}
if (screenBounds.getMaxY() > maxY)
{
maxY = screenBounds.getMaxY();
}
}
return new BoundingBox(minX, minY, maxX - minX, maxY - minY);
}
}
另一个例子:
public class Test extends Application
{
@Override
public void start(Stage primaryStage)
{
Button btn = new Button();
btn.setText("Say 'Hello World'");
btn.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.setContentText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
alert.initOwner(primaryStage);
alert.setOnShown(new EventHandler<DialogEvent>()
{
@Override
public void handle(DialogEvent event)
{
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
//SHOWS ALL NaN NaN NaN NaN
System.out.println(x + " " + y + " " + w + " " + h);
}
});
alert.showAndWait();
}
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
launch(args);
}
}
当您将对话框放置在舞台中央时..只有当舞台也(至少部分地)在您的屏幕之外时,对话框才能在屏幕之外。
请看下面的代码示例..
@Override
public void start(Stage stage) {
Pane pane = new Pane();
Scene scene = new Scene(pane, 800, 500);
Button button = new Button("Alert");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("This is an alert!");
alert.initOwner(stage);
alert.setOnShown(new EventHandler<DialogEvent>() {
@Override
public void handle(DialogEvent event) {
System.out.println(alert.getOwner().getX());
System.out.println(alert.getOwner().getY());
//Values from screen
int screenMaxX = (int) Screen.getPrimary().getVisualBounds().getMaxX();
int screenMaxY = (int) Screen.getPrimary().getVisualBounds().getMaxY();
//Values from stage
int width = (int) stage.getWidth();
int height = (int) stage.getHeight();
int stageMaxX = (int) stage.getX();
int stageMaxY = (int) stage.getY();
//Maximal values your stage
int paneMaxX = screenMaxX - width;
int paneMaxY = screenMaxY - height;
//Check if the position of your stage is not out of screen
if (stageMaxX > paneMaxX || stageMaxY > paneMaxY) {
//Set stage where ever you want
}
}
});
alert.showAndWait();
}
});
pane.getChildren().add(button);
stage.setScene(scene);
stage.show();
}
当使用 showAndWait 时,警报中 onShown 处理程序的(对我来说出乎意料的)问题是,在调用处理程序时,警报尚未显示且尚未显示 sized/located - 这有点疯狂并且可能被认为是错误。
一种解决方法是监听警报的 showingProperty 并在该监听器中进行任何 size/location 调整。类似的东西(显然只是一个 poc)
alert.showingProperty().addListener((src, ov, nv) -> {
double x = alert.getX();
double y = alert.getY();
double w = alert.getWidth();
double h = alert.getHeight();
// as example just adjust if location top/left is off
// production must cope with bottom/right off as well, obviously
if (x < 0) {
alert.setWidth(w + x);
alert.setY(0);
}
if (y <0) {
alert.setHeight(h + y);
alert.setY(0);
}
});
alert.showAndWait();
仅供参考:我真的认为这是一个错误,所以提交了一个issue让我们看看会发生什么