netbeans JavaFX 20在同一屏幕上打开新窗口

a2mppw5e  于 8个月前  发布在  Java
关注(0)|答案(1)|浏览(70)

我有一个小的javafx 20应用程序,它显示一个包含列表的主窗口(带有CSS的FXML)。双击任何行将打开一个新窗口来编辑该行。
问题是,如果主窗口位于辅助屏幕上,则编辑窗口将在主屏幕上打开,而不是在主窗口打开的辅助屏幕上打开。
我尝试使用xProperty()和yProperty()双精度值,保存为设置,将第二个窗口定位为打开,但这只在主窗口上有效。编辑窗口似乎仅限于主屏幕的值。
有没有办法得到打开它的屏幕,并使用该屏幕的x和y,而不是主屏幕。
顺便说一句,NetBeans在主屏幕中运行。这可能是一个线索,也许不是。

更新

好吧,我已经尝试了很多方法,包括下面建议的方法。以下是应用程序当前状态的一些片段:
mainwindow.java在主屏幕上启动,但x和y将其放置在辅助屏幕上。

public Window getOwner()
        {
            stage.getOwner();
        }
        ...
        private void actionEntryEdit()
        {
            int sel_id;

            FXMLLoader editloader;
            DlgPopupEditController maincont = null;
            Parent editroot = null;
            Stage  editstage = null;
            Scene  editscene;

            if ( tblNotesView.getSelectionModel().getSelectedItem() != null ) 
            {
                Note selnote = selModel.getSelectedItem();
                sel_id = selnote.getID();
            }
            else
            {
                sel_id = -1;
            }
            // we have selected a row so get it to the edit window    
            if ( sel_id > 0 )
            {
                editstage.toFront();
                maincont.setNote(sel_id);
                editstage.show();
            }
        }

dlgpopupedit.java,其中存储的设置应将其放置在扩展的第二屏幕上:

@Override
    public void initialize(URL url, ResourceBundle rb)
    {
        initLocalVars();
        readSettings();
    }
    ...
    public void setController(MainWindowController mwc)
    {
        MWC = mwc;
        stage.initOwner(MWC.getOwner());
    }
    ...
    public void setScene(Scene sc)
    {
        displaySettings();
    }

注意:设置保存在Windows风格的.ini文件中(使用XNUMX 4J),作为来自xProperty()和yProperty()双精度值的双精度值。

yb3bgrhw

yb3bgrhw1#

嗯,这比我想象的更有意思。

tl;dr

如果你想得到正确的行为,请重新设置每个新打开窗口的X & Y属性。

  • 默认情况下,新窗口在 * 原始 * 监视器上打开。
  • 如果X和Y发生碰撞,则在 * 当前 * 监视器上打开新窗口。

哪个显示器不同

我看到的行为各不相同,这取决于您的代码是否重新定位新打开的窗口。👉🏼

  • 如果你简单地执行new Stage & stage.show(),JavaFX会坚持在应用程序启动时首次使用的显示器/监视器上打开新窗口。用户可以将窗口移动到另一个显示器/监视器上,但JavaFX坚持在第一个显示器上打开新窗口。奇怪。JavaFX似乎不知道其他显示的存在,即使该显示包含当前窗口。
  • 如果你是程序员,**以编程方式在new Stagestage.show()之间移动载物台,**行为会改变。现在JavaFX展示了我们所期望的行为。新窗口出现在包含当前窗口的显示屏上。如果用户将当前窗口拖到另一个显示器上,新窗口将出现在那里,而不是回到原始显示器上。这种行为是有道理的......但奇怪的是,通过编程重新定位舞台触发了这种明智的行为,但默认情况下,我们得到了奇怪的行为。

示例应用

这种行为很容易证明。看看下面的小例子。我希望有人能验证我的代码,看看我是否做错了什么。
要使用该应用程序:
1.单击“打开另一个窗口”按钮,将“现在”窗口移动到另一个显示器/监视器,然后再次单击该按钮。请注意新窗口出现在原始显示上的奇怪行为。
1.在第二个显示屏上,选中 Relocate each new window 复选框。然后单击“打开另一个窗口”按钮。请注意,新窗口现在显示在第二个显示屏上,而不是原来的显示屏上。行为端正。
1.关闭 * 重新定位每个新窗口 * 复选框,并看到奇怪的行为返回。
我猜这个奇怪的行为是一个bug,但我真的不能辨别。
我在MacBook Pro 16"(Apple Silicon,M1 Pro)上使用Java 20.0.2上的JavaFX 20.0.2,并通过DisplayPort连接BenQ 32英寸4K显示器,macOS Ventura,从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 )
    {
        // Widgets
        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" );

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

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

**警告:**我是一个JavaFX新手,所以我的理解可能是错误的。

相关问题