我有一个像这样定义的自定义控件:
<fx:root type="javafx.scene.Group" xmlns:fx="http://javafx.com/fxml" fx:controller="com.theCorp.theTool.controllers.LimitsController">
<Group id="Group" layoutX="0.0" layoutY="0.0">
<children>
<Group id="Count" layoutX="0.0" layoutY="20.0">
<children>
<Label layoutX="0.0" layoutY="3.0" prefWidth="59.0" text="Count" />
<TextField id="Count.Min" fx:id="countMin" layoutX="59.0" layoutY="0.0" prefWidth="132.0" promptText="Min" />
<TextField id="Count.Max" fx:id="countMax" layoutX="191.0" layoutY="0.0" prefWidth="132.0" promptText="Max" />
</children>
</Group>
<Button id="SaveButton" fx:id="saveButton" layoutX="12.0" layoutY="85.0" mnemonicParsing="false" onAction="#save" text="Save" />
</children>
</Group>
</fx:root>
我有一个Control
类,以通常的方式加载它:
public class LimitsControl extends Group {
private static final String fxmlFileName = "Limits.fxml";
public LimitsControl() {
super();
URL fxml = getClass().getResource(fxmlFileName);
if (fxml == null) {
fxml = getClass().getResource("/fxml/" + fxmlFileName);
}
// Create the loader.
FXMLLoader loader = new FXMLLoader(fxml);
loader.setRoot(this);
try {
// Load the fxml.
loader.load();
// Pull back the controller.
LimitsController controller = loader.getController();
// Tell it about me.
controller.setControl(this);
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
我有一个Controller
类看起来有点像这样:
public class LimitsController implements Initializable {
// Control.
private LimitsControl control;
@FXML
private TextField countMin;
@FXML
private TextField countMax;
@FXML
private Button saveButton;
/**
* Initializes the controller class.
*
* @param url
* @param rb
*/
@Override
public void initialize(URL url, ResourceBundle rb) {
log.info("Loading: " + url + " rb=" + rb+" control="+control);
// Make the save button call my save.
saveButton.setOnAction((ActionEvent e) -> {
save(e);
});
}
public void setControl(LimitsControl control) {
log.info("Control="+control);
this.control = control;
}
@FXML
private void save(ActionEvent event) {
// What is the ID of me?
Parent myGroup = saveButton.getParent();
// Pull the id of the control that enclosed my group.
String myId = myGroup.getParent().getId();
log.info("Saving: " + myId);
}
}
我在几个地方的场景中插入这些控件,每次使用不同的id
,如下所示:
<TitledPane fx:id="Today" animated="false" text="Today">
<tooltip>
<Tooltip text="Parameters will only be used for today." />
</tooltip>
<content>
<LimitsControl id="Today.Limits" />
</content>
</TitledPane>
我的问题是这些控件必须从需要id
控件的数据中填充,但是当控制器初始化时,它没有父控件。
按下保存按钮时id
可用 - 请参阅攀爬父树的save
方法以收集控件的ID。遗憾的是,父级在初始化时为空。
如何在父ID可用时正确初始化字段?或者我做错了还有right
方式?
答案 0 :(得分:2)
首先,注入控件而不是使用set方法耦合所有内容:
<fx:root type="javafx.scene.Group" xmlns:fx="http://javafx.com/fxml" fx:controller="com.theCorp.theTool.controllers.LimitsController" fx:id="control">
和
// Control.
@FXML
private LimitsControl control;
如果我理解正确,你想要获得的id是LimitsControl本身的id。为了使其可用&#34;早期&#34;,在LimitsControl的构造函数中定义一个参数并在那里设置id:
public LimitsControl(String id) {
super();
setId(id);
// code as before...
}
现在,因为您不再拥有默认构造函数,所以需要为LimitsControl创建一个Builder:
public class LimitsControlBuilder {
private String id ;
private LimitsControlBuilder() {
this.id = "" ;
}
public static LimitsControlBuilder create() {
return new LimitsControlBuilder();
}
public LimitsControlBuilder id(String id) {
this.id = id ;
return this ;
}
public LimitsControl build() {
return new LimitsControl(id);
}
}
现在你可以做到
<LimitsControl id="Today.Limits" />
,一旦调用构造函数,就会设置它。
您当然可以在此处创建自己的属性,而不是使用id,这可能是fxml将信息传递给自定义控件实例比使用css id更合适的方式。