将自定义FXML属性设置为自定义javafx组件的参数

德米特里·拉扎列夫(Dmitry Lazarev)

我创建了自定义组件TableBlock。它由Label和TableView组成。TableView可以具有1到1000行。行数由FXML文件中的参数“ rowsFromPrefs”定义。创建TableView时需要此参数。TableView是完全由JAva代码创建的,在fxml中只是其标记和带有多行的参数。

据我所知,当JavaFX构造FXML组件时,它首先调用构造函数,然后调用@FXML带注释的字段,然后启动initialize()方法。

在我的情况下,当initialize()启动时,变量rowsFromPrefs仍然为null!但是,如果我尝试从其他线程(而不是JavaFX-launcher)中获取rowsFromPrefs的值,我会看到它像应该那样定义为“ 2”。

所以我不明白Java在什么时候从FXML文件分配对象参数。创建参数时,如何将参数从fxml文件传递给对象。

我看到了@NamedArg注释的构造函数参数。它是创建对象时传递参数的唯一方法吗?

控制器可以定义一个initialize()方法,当其关联文档的内容已完全加载时,将在实现控制器上调用一次:

TableBlock.java

public class TableBlock extends VBox{
    @FXML
    private String rowsFromPrefs;
    @FXML
    private Label label;

public TableBlock() {
    FXMLLoader fxmlLoader = new   FXMLLoader(getClass().getResource("TableBlock.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@FXML
public void initialize() {
    this.table = createTable(rowsFromPrefs);
}

public String getRowsFromPrefs() {
    System.out.println("getRowsFromPrefs");
    return rowsFromPrefs;
}


public void setRowsFromPrefs(String rowsFromPrefs) {
    this.rowsFromPrefs = rowsFromPrefs;
}

}

TableBlock.fxml

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

<?import javafx.scene.control.*?>
<?import ru.laz.model.controls.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<?import ru.laz.model.controls.tableblock.*?>


<fx:root type="javafx.scene.layout.VBox" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Label text="Label" />
   </children>
</fx:root>

View.java

public class View extends Application {
Parent root = null;
private Scene scene;

@Override
    public void init() {
    try {
            root = FXMLLoader.load(getClass().getResource("View.fxml"));
            root.requestLayout();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
}

@Override
    public void start(final Stage stage) throws Exception {
     scene = new Scene(root, 640, 480, Color.LIGHTGRAY);
     stage.show();
}

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

}

View.fxml

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

<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.control.*?>
<?import ru.laz.model.controls.tableblock.*?>


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <TableBlock rowsFromPrefs="2" id="IDDQD"/>
   </children>
</AnchorPane>
詹姆斯_D

首先,请注意,上面的@FXML注释rowsFromPrefs没有任何作用。@FXML当当前对象为控制器的FXML文件具有一个fx:id属性值与字段名称匹配的元素时,将导致为该字段注入值。由于TableBlock.fxml没有元素fx:id="rowsFromPrefs",因此该注释没有任何作用。

FXMLLoader正在加载的View.fxml遇到<TableBlock>元素时,它将TableBlock通过调用其构造函数来创建实例。然后它将设置属性指定的值。因此,您的FXML元素

<TableBlock rowsFromPrefs="2" id="IDDQD"/>

基本上等于

TableBlock tableBlock = new TableBlock();
tableBlock.setRowsFromPrefs("2");
tableBlock.setId("IDDQD");

当然,构造函数的作用TableBlock只是执行代码说明的操作:它创建一个FXMLLoader,设置根和控制器FXMLLoader,然后调用load()用于负载过程的是 FXMLLoader将设置@FXML在控制器(该上-injected字段TableBlock,其构造为执行的对象),然后调用initialize()

因此,在构造函数中,initialize()作为调用的一部分被调用当然,这一切都是在调用之前发生的FXMLLoader.load()TableBlocksetRowsFromPrefs("2");

因此,总而言之,在解析TableBlock.initialize()之后调用TableBlock.fxml,并将其中定义的任何元素注入到其相应的带@FXML注释的字段中,但这View.fxml是在加载之前发生的

解决此问题的一种方法是传递rowsFromPrefsTableBlock构造函数。为此,请使用@NamedArg注释

public class TableBlock extends VBox{

    private final String rowsFromPrefs;

    @FXML
    private Label label;

    public TableBlock(@NamedArg("rowsFromPrefs") String rowsFromPrefs) {

        this.rowsFromPrefs = rowsFromPrefs ;
        FXMLLoader fxmlLoader = new   FXMLLoader(getClass().getResource("TableBlock.fxml"));
        fxmlLoader.setRoot(this);
        fxmlLoader.setController(this);
        try {
            fxmlLoader.load();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    public void initialize() {
        this.table = createTable(rowsFromPrefs);
    }

    public String getRowsFromPrefs() {
        System.out.println("getRowsFromPrefs");
        return rowsFromPrefs;
    }


}

现在,FXML中的属性将传递给构造函数,而不是set方法,因此rowsFromPrefs将在调用之前fxmlLoader.load()根据需要进行初始化

当然,另一个选择只是将代码从initialize()方法移到setRowsFromPrefs(...)方法。如果打算rowsFromPrefs针对每个TableBlock实例进行修复,则将使用上述选项,并且仅当您希望能够rowsFromBlocks在单个TableBlock实例的生命周期内进行更改时,才使用第二个选项

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将自定义参数添加到自定义组件“components”属性

角度自定义组件属性设置

将自定义属性定义为数据对象

如何扩展使用FXML的自定义JavaFX组件

JavaFx 在 FXML 中包含自定义组件

将自定义属性传递到Aurelia组件

android通过编程将自定义值设置为自定义textview

如何将自定义标记设置为自定义视图?

如何将自定义tabBar设置为我的自定义TabBarController?

将自定义样式设置为android中的自定义视图内的textviews

将自定义域设置为“主要”的好处

将自定义 ActionBar 重力设置为 RIGHT

将自定义字体设置为微调器

在OpenCv中将自定义模型设置为CvSVM

Android:将自定义值设置为NumberPicker

将自定义chipDrawable背景设置为Chip

如何将自定义委托设置为UITableViewController?

设置自定义属性

如何将自定义管理器类参数设置为 required=False

将自定义C ++容器的大小设置为模板参数与构造函数

如何通过 XAML 标记将自定义类实例设置为 Button.Content 属性?

将自定义对象设置为微调框并显示特定属性

HTML select onchange获取将自定义属性值设置为其他输入值

自定义组件JavaFX的自定义操作发射器属性-如何?

在intelliJ中将自定义组件添加到FXML场景构建器

在 connectedCallback 中自定义 Web 组件设置属性

如何在 JavaFx 中为自定义组件创建属性?

如何使用 TinyMCE 为自定义组件设置样式?

在JavaFX中添加自定义组件