【问题标题】:JavaFX: Is it possible to use variable resolution in "fx:define"JavaFX:是否可以在“fx:define”中使用变量解析
【发布时间】:2016-10-17 16:23:50
【问题描述】:

我正在尝试使用 fx:define 定义动态评估变量,但我无法从另一个变量中获得要评估的变量,我什至不知道这是否可能?

<GridPane hgap="${10*m.dp}" vgap="${10*m.dp}" xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1">
    <fx:define>
        <Measurement fx:id="m" />
        <!-- This works, but is not what I need -->
        <Double fx:id="width" fx:value="300" />
        <!-- This doesn't work -->  
<!--        <Double fx:id="width" fx:value="${300*m.dp}" /> -->
    </fx:define>
    <padding>
        <Insets bottom="$width" left="$width" right="$width" top="$width" />
    </padding>
    <Text text="hello" />
    <Button GridPane.rowIndex="1" text="button" prefWidth="${300*m.dp}" />
    <Button GridPane.rowIndex="2" text="button2" prefWidth="$width" />
</GridPane>

我在这里想要的是从我计算的 dp 计算宽度(密度独立像素 - 在高清屏幕中值为 1,在 4K 屏幕中为 2,在我的 1600px 宽度屏幕上为 0.xx)。我想要的“宽度”变量在我的真实案例中用于很多组件,这就是我想要一个变量的原因 - 为了简洁。

运行它的java代码

public class Measurement {
  private double dp;

  public Measurement(){
    Screen primary = Screen.getPrimary();
    dp=primary.getBounds().getWidth()/1920;
  }

  /** 
   * Equivalent of 1 px in 1920. 
   */
  public double getDp(){
    return dp;
  }

  public void setDp (double dp) {
    this.dp = dp;
  }

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

  @Override
  public void start (Stage primaryStage) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader();
    Parent root = fxmlLoader.load(getClass().getResource("index.fxml").openStream());
    Scene scene = new Scene(root, 300, 275);
    primaryStage.setMaximized(true);
    primaryStage.setScene(scene);
    primaryStage.show ();
  }


}

其实我也不清楚可以用哪个和在哪里表达,我在这里看到很多答案:Is it possible to use arithmetic expression in FXML?

这里:Bind Font Size in JavaFX?

这里: http://docs.oracle.com/javase/8/javafx/api/javafx/fxml/doc-files/introduction_to_fxml.html#expression_binding

不明白在什么情况下可以使用表达语言,有规范吗?

已编辑:我添加了指向 javafx-8 文档的链接,并删除了对 javaFX-2 的过时评论

【问题讨论】:

  • 你可以使用多个fx:define标签吗?是这样,也许可以尝试看看是否可以看到前者的定义。
  • @Cyrille_Pontvieux 是的,我们可以,我试过了,但它没有任何改变,它很像定义块的多个声明,具有相同的变量声明,但如果我知道“fx”的实现在哪里:define" 是,我可以尝试调试。

标签: java javafx-8


【解决方案1】:

为时已晚,但这可能对某人有所帮助。当您在&lt;fx:define&gt; 块内使用&lt;Double fx:id="width" fx:value="300"/&gt; 时,FMXLLoader 会进入声明的类型,在这种情况下为Double,并尝试调用方法Double.valueOf("300"),这是有效的,因为此调用返回具有值的Double 对象300 个。 当您使用&lt;Double fx:id="width" fx:value="${300*m.dp}"/&gt; 时,将抛出NumberFormatException,因为值“${300*m.dp}”不代表有效的双精度值。

FXMLLoader 仅在类型可观察时才计算以“${”开头的表达式。 为了在 FXML 中将一个值绑定到另一个值,它们都应该是可观察的属性。在您的情况下,您可以将以下属性添加到 Measurement 类:

public class Measurement {
    public final DoubleProperty dp = new SimpleDoubleProperty();

    public Measurement() {
        Screen primary = Screen.getPrimary();
        dp.set(primary.getBounds().getWidth() / 1920.0);
    }

    public double getDp() {
        return dp.get();
    }

    public void setDp(double dp) {
        this.dp.set(dp);
    }

    public final DoubleProperty widthProperty() {
        if (width == null) {
            width = new SimpleDoubleProperty();
            width.bind(dp.multiply(300.0));
        }
        return width;
    }

    private DoubleProperty width;

    public final double getWidth() {
        return width == null ? 0 : width.get();
    }
}

然后在你的 FXML 中像这样使用它:

<fx:define>
    <Measurement fx:id="measurement"/>
</fx:define>
<Button prefWidth="${measurement.width}" />

注意:恕我直言,我认为您不需要使 Measurement 类可实例化。重复相同的措施并在每个 FXML 文件中创建新实例是没有意义的。另一种解决方案是具有私有构造函数的类,该构造函数包含静态属性并通过调用 &lt;fx:factory&gt;&lt;fx:constant&gt; 在 FXML 中使用。

【讨论】:

  • 在fxml而不是java中写大小怎么样,可以吗?用法是将许多按钮的大小设置为 300*dp,例如,一些按钮的大小为 400*dp,以实现 4K 兼容性。
  • 您可以在 FXML 中定义width 属性,并使用注释@FXML 在您的代码中对其进行初始化。如果您有多个配置,则可以使用两个不同的属性,比如widthwidth4k。第一个将绑定到 dp*300,另一个将绑定到 dp*400。如果您有任何问题,我可以帮助您实施。
猜你喜欢
  • 2014-10-04
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
  • 2019-10-28
  • 2017-11-18
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多