JavaFX:支持不同分辨率

5
我正在尝试理解如何在JavaFX中支持不同的分辨率。我正在寻找一种关于如何实现这一点的指南。
我想创建一个应用程序,需要最低分辨率为1280×720。并且我希望我的应用程序在任何更高的分辨率下看起来都很好(比如1920×1080)。此外,该应用程序应在不同的DPI值下看起来良好。我该怎么做?
让我们将JDK 11.0.2+和JavaFX 11.0.2+作为最低要求,以更具体地说明。
我现在(似乎)理解的是:
1.必须设置舞台的最小宽度和高度。
2.我不必担心DPI支持,因为它似乎已经实现了
我仍然不理解的是:
  1. 如何设置元素的尺寸、缩进等。
    • 我应该针对最小支持的分辨率设置像素值,然后根据当前分辨率乘以系数吗?
    • 还是应该将大小建立为屏幕宽度/高度的百分比?
    • 或者应该用完全不同的方式来完成?
  2. 我应该避免任何控件/布局吗?

我希望我表达得足够清楚。

我是新手,开始创建实际应用程序的界面。我将感激任何帮助,包括注释、解释、代码示例或链接到文章。

提前感谢您的帮助。


2
这取决于您正在创建的应用程序类型。如果应用程序由标准UI元素组成,例如按钮、文本字段和表格,则答案是您无需做任何事情:只需使用布局类并让默认首选大小计算为您完成工作即可。如果您正在制作游戏,则可能会更加复杂,这取决于您想要做多少工作。 - VGR
@VGR 我正在创建一个不是很复杂的客户端应用程序。因此,它由标准UI元素组成。但我不太理解“默认首选大小计算”语句。例如,如果我有一个按钮,它需要被调整大小。而且这个大小应该根据不同的分辨率而不同。 - DfM
4个回答

10

那是一个非常好的问题,因为JavaFX不支持实时响应式分辨率,所以你必须自己来做。

  1. 首先尝试依靠不同的布局来根据计算出的位置、宽度和高度分配UI组件,比如在BorderPane中有5个部分可以轻松设置你的组件。
  2. 在完成第一步后,如果仍然有一些想要自定义修改宽度和高度的组件,请设置您希望的宽度和高度,并将这些值乘以一个比例。您可以通过获取屏幕分辨率来计算这个比例,因此下一次在不同分辨率的屏幕上运行应用程序时,该组件的宽度或高度会不同。
  3. 您还可以为应用程序支持的每个分辨率提供不同的 FXML 文件,以便您可以运行适当的设计,也可以适用于横向和纵向的情况。
  4. 当然,您还可以寻找第三方库,例如提供响应式组件的类似于Web设计的BootstrapFX,还有ResponsiveFX,但我以前没有尝试过它们。

我希望我的答案能帮助您或引导您走向制作一些酷炫应用的正确方向。


6

每个组件(按钮、文本框等)都会根据分辨率、字体大小、用户选择的主题等计算自己的首选大小。你所要做的就是确保不干扰它们。所以不要设置任何尺寸。

当你将组件放置在布局中(除了AnchorPane之外的任何Pane子类),布局将尽力尊重每个子组件的首选大小。在大多数应用程序中,你永远不需要显式地设置一个单独的宽度或高度。


那么基本上我只需要设置舞台的最小宽度和高度吗?如果我希望某些组件不超过特定大小怎么办?例如,标签可能具有不同长度的文本。 请参见此代码粘贴此屏幕截图 - DfM
2
你不应该设置舞台(Stage)或场景(Scene)的尺寸。默认情况下,舞台的尺寸设置为场景的大小,并且场景会容纳所有节点(Nodes)的首选大小。如果你有一个可能包含长文本的标签(Label),则可以设置其最大尺寸,但通常较长的文本会放在TextField或TextArea中,这些组件会自动处理长文本。 - VGR
谢谢您的解释。但是我确实需要设置大小,因为在某些窗格中,元素将以动态方式出现,即它们可能根本不会出现。在这种情况下,这些窗格将根本不占用任何空间。您建议如何设置大小? - DfM
我不明白为什么这需要你设置大小。如果你不想让一个窗格出现,就在它上面调用 setVisible(false) - VGR
我需要一些不同的东西。即使没有任何元素,我也想要一个窗格出现。 - DfM
2
我猜你想要一个StackPane,其中包含一个空节点和常规用户界面。如果没有更多关于你正在尝试做什么的信息,我无法确定。 - VGR

1

你可以尝试使用不同的fxml文件:

MaximizedPane.fxml: --> 查看prefWidth / perfHight

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.control.Label?>
<?import javafx.stage.Screen?>

<StackPane xmlns:fx="http://javafx.com/fxml/1"
           prefWidth="${screen.visualBounds.width}" 
           prefHeight="${screen.visualBounds.height}" >
    <fx:define>
        <Screen fx:factory="getPrimary" fx:id="screen"/>
    </fx:define>
    <Label text="A maximized pane"/>    
</StackPane>

动态加载fxml文件:
import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class MaximizedFXMLPane extends Application {

    @Override
    public void start(Stage primaryStage) throws IOException {
        Scene scene = new Scene(FXMLLoader.load(getClass().getResource("MaximizedPane.fxml")));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

我在我的git存档中提供了一个示例:https://github.com/src-mgra/my-calendar/blob/master/MyCalendar/src/sample/Main.java


另一种方法是使用场景:
import java.awt.Dimension;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class ScreenResolutionDemo extends Application {


    @Override
    public void start(Stage primaryStage) throws Exception {
        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        double width = screenSize.getWidth() / 3;
        double height = screenSize.getHeight() / 2;

        try {
            **primaryStage.setScene**(new Scene(new AnchorPane(), *width*, **height**));
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

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

}

0

我目前正在构建一个桌面应用程序,几乎具有相同的限制。一个月前我遇到了这个问题,但后来发现我不需要做任何事情。 Pane将根据屏幕分辨率自动调整内部元素的大小。正如VGR所正确提到的,Anchorpane不会调整子元素的大小,因此我需要用Pane替换所有Anchorpane。

在其中一台测试机上遇到的另一个问题是,舞台在低分辨率显示器上显示过大,并且没有自动调整大小。 为了解决这个问题,我将屏幕分辨率设置为另一个值,然后将其切换回原始值,问题就解决了。

您需要设置舞台的最小和(或)最大大小,并将其设置为不可调整大小,这样就可以解决问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接