防止对话框关闭

时间:2018-08-28 16:15:07

标签: java javafx javafx-8

我有一个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 :(得分:2)

使用showAndWait时,警报上的onShown处理程序出现(对我来说是意外的)问题是,在调用处理程序时,警报尚未显示且尚未设置大小/位置-这有点疯狂,可能是被认为是错误。

一种解决方法是监听警报的showingProperty并在该监听器中进行任何大小/位置调整。像(显然是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让我们看看会发生什么

答案 1 :(得分:1)

当您将对话框放置在舞台中央时。如果舞台也(至少部分地)在屏幕之外,则对话框只能显示在屏幕外。

请参见下面的代码示例。

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