stage/scene 和屏幕之间需要清晰

need clarity between stage/scene and screen

以下基本代码可以完美运行。它确定可用屏幕列表,然后识别最大的屏幕,然后将舞台的大小设置为等于最大监视器的尺寸。

public class MaximizedStage extends Application {
public static void main(String[] args) {
    Application.launch(args);
}

@Override
public void start(Stage stage) {
    ObservableList<Screen> monitors = Screen.getScreens();
    //determine the larger monitor
    Rectangle2D bounds = monitors.get(0).getVisualBounds();     //get the bounds of the default monitor
    int preferred_mon = 0;
    var x = bounds.getMinX();
    var y = bounds.getMinY();
    var w = bounds.getWidth();
    var h = bounds.getHeight();
    System.out.println("Count of monitors : "+monitors.size()+" default monitor size : w: "+w+" h: "+h);
    for (int mon = 1; mon < monitors.size(); mon++) {           // for each of the other monitors
        Rectangle2D next_monitor_bounds = monitors.get(mon).getVisualBounds();  //get the size
        if ((next_monitor_bounds.getHeight() > h) && (next_monitor_bounds.getWidth() > w)) {
            //larger monitor, update parameters
            preferred_mon = mon;
            x = next_monitor_bounds.getMinX();
            y = next_monitor_bounds.getMinY();
            w = next_monitor_bounds.getWidth();
            h = next_monitor_bounds.getHeight();
        }
    }
    System.out.println("Largest monitor : index: "+preferred_mon+" w: "+w+" h: "+h);

    stage.setScene(new Scene(new Group()));
    stage.setTitle("Full screen");

    // Set the position and size of the stage equal to the position and
    // size of the screen

    stage.setX(x);
    stage.setY(y);
    stage.setWidth(w);
    stage.setHeight(h);

    // Show the stage       
    stage.show();
}
}

我的问题是:在这段代码中,舞台(或场景)在哪里知道要显示的屏幕中的最终选择是哪个?我正在努力理解 stage/scene 和显示器选择之间的联系。最后的 objective 是准备多个不同的阶段,运行 每个阶段在不同的线程上,并将它们的输出定向到不同的监视器。

感谢您的关注。

每个屏幕的边界都是相对于某个虚拟坐标系的。边界描述了每个屏幕的宽度和高度,还描述了屏幕在该坐标系中的位置,从而定义了不同显示设备之间的相对位置。通常,这些是由 OS 级别的用户首选项设置定义的。

在我当前使用的设置中,我将 MacBook Pro 连接到外部显示器(配置为主显示器)。在系统偏好设置中,这看起来像:

这与我所拥有的物理布局非常接近。这意味着我可以将 windows 从主屏幕(如右图所示)拖动到该屏幕的左边缘,然后拖到笔记本电脑屏幕(如左图所示)上。

大屏幕尺寸为 3008x1692,笔记本电脑屏幕尺寸为 1680x1050。边界报告为

Rectangle2D [minX = 0.0, minY=0.0, maxX=3008.0, maxY=1692.0, width=3008.0, height=1692.0]
Rectangle2D [minX = -1680.0, minY=213.0, maxX=0.0, maxY=1263.0, width=1680.0, height=1050.0]

所以主屏幕列在第一位,位置为 (0,0),笔记本电脑屏幕列在第二位,向左偏移 1680 像素,比主屏幕低 213 像素。

在您的代码中,舞台的 xy 坐标设置为在此选择的(最大)屏幕的 xy 坐标坐标系,因此舞台的左上角将位于该屏幕的左上角。通过将舞台的宽度和高度设置为屏幕的宽度和高度,舞台将完全填满该屏幕(尽管您可能会丢失系统任务栏或停靠栏后面的一些舞台)。

这是一个类似的测试示例,它使 window 成为屏幕宽度和高度的一半,并居中:

import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Screen;
import javafx.stage.Stage;

import java.io.IOException;

public class ScreenDemo extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        VBox buttons = new VBox(5);
        buttons.setFillWidth(true);
        buttons.setAlignment(Pos.CENTER);
        int index = 1 ;
        for (Screen screen : Screen.getScreens()) {
            System.out.println(screen.getBounds());
            Button button = new Button("Screen "+index);
            button.setOnAction(e -> centerInScreen(stage, screen));
            button.setMaxWidth(Double.MAX_VALUE);
            buttons.getChildren().add(button);
            index++;
        }
        HBox root = new HBox(buttons);
        root.setFillHeight(true);
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        centerInScreen(stage, Screen.getPrimary());
        stage.show();
    }

    private void centerInScreen(Stage stage, Screen screen) {
        // make window half screen size and center in screen:
        Rectangle2D screenBounds = screen.getBounds();
        double x = screenBounds.getMinX();
        double y = screenBounds.getMinY();
        double w = screenBounds.getWidth();
        double h = screenBounds.getHeight();
        stage.setX(x + w/4);
        stage.setY(y + h/4);
        stage.setWidth(w/2);
        stage.setHeight(h/2);
    }

    public static void main(String[] args) {
        launch();
    }
}

这是一个类似的示例,它在每个屏幕中都将舞台居中:

import javafx.application.Application;
import javafx.geometry.Rectangle2D;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Screen;
import javafx.stage.Stage;

import java.io.IOException;

public class ScreenDemo extends Application {
    @Override
    public void start(Stage stage) throws IOException {

        int index = 1 ;
        for (Screen screen : Screen.getScreens()) {
            if (screen != Screen.getPrimary()) {
                Label label = new Label("Window in screen "+index);
                BorderPane root = new BorderPane(label);
                Scene scene = new Scene(root);
                Stage window = new Stage();
                window.setScene(scene);
                centerInScreen(window, screen);
                window.show();
            }
            index++;
        }
        Label label = new Label("Window in primary screen");
        BorderPane root = new BorderPane(label);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        centerInScreen(stage, Screen.getPrimary());
        stage.show();
    }

    private void centerInScreen(Stage stage, Screen screen) {
        // make window half screen size and center in screen:
        Rectangle2D screenBounds = screen.getBounds();
        double x = screenBounds.getMinX();
        double y = screenBounds.getMinY();
        double w = screenBounds.getWidth();
        double h = screenBounds.getHeight();
        stage.setX(x + w/4);
        stage.setY(y + h/4);
        stage.setWidth(w/2);
        stage.setHeight(h/2);
    }

    public static void main(String[] args) {
        launch();
    }
}