我有一个小型 javafx 20 应用程序,它显示一个包含列表的主窗口(带 CSS 的 FXML)。双击任何行将打开一个新窗口来编辑该行。
问题是,如果主窗口位于辅助屏幕上,则编辑窗口将在主屏幕上打开,而不是在主窗口打开的辅助屏幕上打开。
我尝试使用 xProperty() 和 yProperty() 双精度值(另存为设置)来将第二个窗口定位为打开状态,但这仅适用于主窗口。编辑窗口似乎仅限于主屏幕的值。
有没有办法获取打开它的屏幕并使用该屏幕的 x 和 y 而不是主屏幕。
顺便说一句,NetBeans 在主屏幕中运行。这可能是一个线索...也许不是。
嗯,事实证明这是一个比我预想的更有趣的挑战。
我看到的行为有所不同,具体取决于 👉🏼 您的代码是否重新定位新打开的窗口。
new Stage
和stage.show()
,JavaFX会坚持在应用程序启动时首次使用的显示器/监视器上打开新窗口。用户可以将窗口移动到另一个显示器/监视器,但 JavaFX 坚持在第一个显示器上打开新窗口。诡异的。 JavaFX 似乎不知道另一个显示的存在,即使该显示包含当前窗口。new Stage
和stage.show()
之间移动舞台,行为会发生变化。现在 JavaFX 表现出我们期望的行为。新窗口出现在包含当前窗口的显示屏上。如果用户将该当前窗口拖动到另一个显示器,新窗口将出现在那里,而不是返回到原始显示器上。这种行为是有道理的......但是以编程方式重新定位舞台会触发这种明智的行为是多么奇怪,但默认情况下我们会得到奇怪的行为。该行为很容易演示。请参阅下面我的小示例应用程序。我希望有人可以验证我的代码,看看我是否做错了什么。
要使用该应用程序:
我猜测这种奇怪的行为是一个错误,但我无法真正辨别。
我在 MacBook Pro 16"(Apple Silicon、M1 Pro)上使用了 JavaFX 20.0.2 on Java 20.0.2,并通过 DisplayPort、macOS Ventura 连接了 BenQ 32 英寸 4K 显示器,从 IntelliJ IDE 启动。
package work.basil.example.exfxgatherinput;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.stage.Window;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicInteger;
public class OpenWindowApp extends Application
{
private final AtomicInteger countWindows = new AtomicInteger ( 0 );
@Override
public void start ( Stage stage )
{
// Scene
Scene scene = this.makeScene ( false );
// Stage
this.decorate ( stage );
stage.setScene ( scene );
stage.show ( );
}
private void decorate ( Stage stage )
{
stage.setTitle ( "Window # " + this.countWindows.incrementAndGet ( ) );
stage.setWidth ( 380 );
stage.setHeight ( 170 );
}
private Scene makeScene ( final boolean relocateNewWindow )
{
CheckBox relocateEachNewWindow = new CheckBox ( "Relocate each new window" );
relocateEachNewWindow.setSelected ( relocateNewWindow );
Label nowLabel = new Label ( "Window created at: " + Instant.now ( ).toString ( ) );
Button newWindowButton = new Button ( );
newWindowButton.setText ( "Open another window" );
newWindowButton.setOnAction ( ( ActionEvent actionEvent ) ->
{
Stage stage = new Stage ( );
this.decorate ( stage );
stage.setScene ( this.makeScene ( relocateEachNewWindow.isSelected ( ) ) );
if ( relocateEachNewWindow.isSelected ( ) )
{
this.relocateWindow ( actionEvent , stage );
}
stage.show ( );
} );
VBox vbox = new VBox ( relocateEachNewWindow , nowLabel , newWindowButton );
vbox.setPadding ( new Insets ( 20 , 20 , 20 , 20 ) );
vbox.setSpacing ( 12 );
vbox.setAlignment ( Pos.CENTER );
return new Scene ( vbox );
}
private void relocateWindow ( ActionEvent actionEvent , Stage stage )
{
Window currentWindow = ( ( Node ) actionEvent.getSource ( ) ).getScene ( ).getWindow ( );
stage.setX ( currentWindow.getX ( ) + 50 );
stage.setY ( currentWindow.getY ( ) + 50 );
}
public static void main ( String[] args )
{
launch ( );
}
}