JavaFX:是否可以在“ fx:define”中使用可变分辨率

问题描述 投票:5回答:1

我正在尝试使用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的宽度(与密度无关的像素-在HD屏幕上为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的过时注释

java javafx-8
1个回答
1
投票

太晚了,这可能对某人有用。当您在<Double fx:id="width" fx:value="300"/>块内使用<fx:define>时,FMXLLoader会使用声明的类型Double,在这种情况下,它会尝试调用方法Double.valueOf("300"),这是可行的,因为此调用会返回带有值的Double对象300。当您使用<Double fx:id="width" fx:value="${300*m.dp}"/>时,将抛出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文件中创建一个新实例。另一种解决方案是使用带有私有构造函数的类,该类具有静态属性,并通过调用<fx:factory><fx:constant>在FXML中使用。]

© www.soinside.com 2019 - 2024. All rights reserved.