【问题标题】:JavaFX: supporting different resolutionsJavaFX:支持不同的分辨率
【发布时间】:2019-10-01 18:25:02
【问题描述】:

我正在尝试了解如何在 JavaFX 中支持不同的分辨率。我正在寻找有关如何实现这一目标的指南。

我想创建一个应用程序,它需要最小分辨率,例如 1280×720。而且我希望我的应用程序在任何更高的分辨率(如 1920×1080)上也能正常显示。此外,应用程序在不同的 DPI 值下应该看起来不错。 我该怎么做?

让我们将 JDK 11.0.2+ 和 JavaFX 11.0.2+ 设置为更具体的最低要求。

我现在(似乎)明白了什么:

  1. 必须设置舞台的最小宽度和高度。
  2. 我不关心 DPI 支持,就像 it seems to be implemented

我还是不明白:

  1. 如何设置元素的尺寸、缩进等。
    • 是否应该为支持的最小分辨率设置像素值,然后根据当前分辨率乘以系数?
    • 或者我应该将尺寸增加为屏幕宽度/高度的百分比?
    • 或者我应该以完全不同的方式来做这一切?
  2. 我应该避免使用任何控件/布局吗?

我希望我已经足够清楚了。

我不熟悉为真实而非玩具应用程序创建界面。我将不胜感激任何帮助,无论是 cmets、解释、代码示例还是文章链接。

提前感谢您的帮助。

【问题讨论】:

  • 这取决于您正在创建的应用程序的类型。如果应用程序由标准 UI 元素(如按钮、文本字段和表格)组成,答案是您什么都不应该做:只需使用布局类并让默认的首选大小计算为您完成工作。如果您正在制作游戏,则可能会稍微复杂一些,具体取决于您想做多少工作。
  • @VGR 我正在创建一个不是很复杂的客户端应用程序。所以是的,它由标准的 UI 元素组成。但我不太明白“默认首选大小计算”语句。例如,如果我有一个按钮,则需要调整其大小。而且这个尺寸对于不同的分辨率应该是不同的。

标签: java javafx


【解决方案1】:

JavaFX 是一个很好的问题,它不支持即时响应式解决方案,所以你可以自己解决

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

我希望我的回答对你有所帮助,或者让你走上正确的道路来制作一些很酷的应用程序

【讨论】:

    【解决方案2】:

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

    当您将组件放置在布局中(AnchorPane 以外的任何 Pane 子类)时,布局将尽最大努力尊重每个孩子的首选尺寸。在大多数应用程序中,您永远不必明确设置单个宽度或高度。

    【讨论】:

    • 所以基本上我只需要设置舞台的最小宽度和高度?如果我希望某些组件不超过特定大小,该怎么办?例如,标签的文本长度可能不同。见this code pastethis screenshot
    • 您也不应该设置舞台或场景的大小。默认情况下,舞台大小设置为场景的大小,场景容纳所有节点的首选大小。如果您有一个可能包含长文本的标签,您可以设置其最大大小,但通常长文本放置在 TextField 或 TextArea 中,它们会自动处理长文本。
    • 感谢您的解释。但我确实需要设置大小,因为在某些窗格中元素会动态显示,即它们可能根本不会出现。在这种情况下,这些窗格根本不会占用任何空间。您建议如何设置尺寸?
    • 我不明白为什么这需要您的设置大小。如果您不希望显示窗格,请在其上调用 setVisible(false)
    • 我怀疑你想要一个 StackPane,它包含一个空白节点和常规用户界面。如果没有更多关于你想要做什么的信息,我不能肯定地说。
    【解决方案3】:

    您好尝试使用不同的 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);
        }
    
    }
    

    【讨论】:

      【解决方案4】:

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

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

      您将需要设置舞台的最小和(或)最大尺寸,并且(也许)将其设置为不可调整大小并且必须有效。

      【讨论】:

        猜你喜欢
        • 2013-05-18
        • 1970-01-01
        • 2013-04-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-07
        • 1970-01-01
        相关资源
        最近更新 更多