Reputation: 1795
I have a primaryStage which is fine. I have a dialog that opens fine centered on the primaryStage (I got this to work by making the owner to the dialog the primaryStage
dialog.setInitOwner(primaryStage).
However, the dialog will go off-screen if the primaryStage is already close to the edge of the screen. How do I make the dialog (which has the primaryStage as the owner) not go off the screen if the owner is near the edge of the screen?
I've tried this:
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 is created by:
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);
Trying this, doesn't change any behaviour. I feel it's because the dialog.getX() function returns a NaN... }
As requested, an example:
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);
}
}
Another ex:
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);
}
}
Upvotes: 2
Views: 835
Reputation: 51535
The (unexpected for me) problem with the onShown handler on the alert when using showAndWait is that at the time the handler is invoked the alert is not yet showing and not yet sized/located - which is somewhat crazy and probably might be considered a bug.
A way around is to listen to the showingProperty of the alert and do any size/location adjustments in that listener. Something like (just a poc, obviously)
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();
FYI: I really think it's a bug, so filed an issue let's see what happens
Upvotes: 2
Reputation: 73
As you are positioning the dialog in the center of the stage.. the dialog could only be out of the screen if the stage is also (at least partly) outside of your screen.
Please see the following code example..
@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();
}
Upvotes: 1