Предотвратить выход диалога из экрана - PullRequest
0 голосов
/ 28 августа 2018

У меня есть 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 () возвращает 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);
    }

}

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

(неожиданная для меня) проблема с обработчиком onShown для оповещения при использовании showAndWait заключается в том, что во время вызова обработчика оповещение еще не отображается и еще не измерено / не расположено - что несколько странно и, вероятно, может быть считается ошибкой.

Способом обойти это является прослушивание свойства показа предупреждения и выполнение любых настроек размера / местоположения в этом слушателе. Что-то вроде (просто оч, очевидно)

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();

К вашему сведению: я действительно считаю, что это ошибка, поэтому подал вопрос давайте посмотрим, что произойдет

0 голосов
/ 28 августа 2018

Когда вы размещаете диалоговое окно в центре сцены ... диалоговое окно может быть вне экрана, только если сцена также (хотя бы частично) находится за пределами вашего экрана.

Пожалуйста, смотрите следующий пример кода.

@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();
}
...