创建自定义控件以包含其他自定义控件
Create Custom Control to Contain Other Custom Controls
我正在创建一个应引导用户完成步骤的应用程序,如下面的屏幕截图所示:
<Step fx:id="selectConnectionStep" source="SelectConnection" stepLabel="Step 1 : Select a Connection" />
<Step fx:id="selectSObjectStep" source="SelectSObject" stepLabel="Step 2 : Select an SObject" />
<Step fx:id="selectActionStep" stepLabel="Step 3 : Select an Action">
<VBox GridPane.columnSpan="2" GridPane.rowIndex="1">
<Action actionLabel="test" onAction="#test" />
<GridPane.margin>
<Insets bottom="15.0" left="15.0" right="10.0" top="10.0" />
</GridPane.margin>
</VBox>
</Step>
在应用程序中,我将更多场景配置为以这种方式工作,因此我想以易于维护的方式设计它。
我创建了名为 "Step" 的自定义控件(它基本上扩展了 GridPane)
每个 "Step" 都有标题、loadingIcon 和内部组件。
在前两个步骤中,我使用我创建的 'source' 属性加载内部组件。我只是给出组件的 FXML 文件的名称。在代码中,我只是加载 FXML 并将组件放在正确的位置。
但是,正如在第 3 步中所见,我尝试仅将内部组件填充为步骤 child。可以看出这是有效的,但是我希望 Step 将其 child 注入正确的位置,而不指定将其放置在网格中的位置的任何细节。
即
<Step fx:id="selectActionStep" stepLabel="Step 3 : Select an Action">
<VBox>
<Action actionLabel="test" onAction="#test" />
</VBox>
</Step>
如果我不指定任何细节,组件将进入左上角的 GridPane 内。
问题是自定义控件如何操作其 FXML child 元素?
我也可以扩展 GridPane 吗?
谢谢:)
最好的方法是在添加 "standard" 元素后向子列表添加 ListChangeListener
,例如
private static final Insets MARGIN = new Insets(10, 10, 15, 15);
...
// add standard elements...
getChildren().addListener((ListChangeListener.Change<? extends Node> c) -> {
while (c.next()) {
if (c.wasAdded()) {
for (Node n : c.getAddedSubList()) {
GridPane.setColumnSpan(2);
GridPane.setRowIndex(1);
GridPane.setMargin(MARGIN);
}
}
}
});
我还发现了这个 post,它介绍了另一种解决方案:
我正在创建一个应引导用户完成步骤的应用程序,如下面的屏幕截图所示:
<Step fx:id="selectConnectionStep" source="SelectConnection" stepLabel="Step 1 : Select a Connection" />
<Step fx:id="selectSObjectStep" source="SelectSObject" stepLabel="Step 2 : Select an SObject" />
<Step fx:id="selectActionStep" stepLabel="Step 3 : Select an Action">
<VBox GridPane.columnSpan="2" GridPane.rowIndex="1">
<Action actionLabel="test" onAction="#test" />
<GridPane.margin>
<Insets bottom="15.0" left="15.0" right="10.0" top="10.0" />
</GridPane.margin>
</VBox>
</Step>
在应用程序中,我将更多场景配置为以这种方式工作,因此我想以易于维护的方式设计它。
我创建了名为 "Step" 的自定义控件(它基本上扩展了 GridPane)
每个 "Step" 都有标题、loadingIcon 和内部组件。
在前两个步骤中,我使用我创建的 'source' 属性加载内部组件。我只是给出组件的 FXML 文件的名称。在代码中,我只是加载 FXML 并将组件放在正确的位置。 但是,正如在第 3 步中所见,我尝试仅将内部组件填充为步骤 child。可以看出这是有效的,但是我希望 Step 将其 child 注入正确的位置,而不指定将其放置在网格中的位置的任何细节。
即
<Step fx:id="selectActionStep" stepLabel="Step 3 : Select an Action">
<VBox>
<Action actionLabel="test" onAction="#test" />
</VBox>
</Step>
如果我不指定任何细节,组件将进入左上角的 GridPane 内。
问题是自定义控件如何操作其 FXML child 元素? 我也可以扩展 GridPane 吗?
谢谢:)
最好的方法是在添加 "standard" 元素后向子列表添加 ListChangeListener
,例如
private static final Insets MARGIN = new Insets(10, 10, 15, 15);
...
// add standard elements...
getChildren().addListener((ListChangeListener.Change<? extends Node> c) -> {
while (c.next()) {
if (c.wasAdded()) {
for (Node n : c.getAddedSubList()) {
GridPane.setColumnSpan(2);
GridPane.setRowIndex(1);
GridPane.setMargin(MARGIN);
}
}
}
});
我还发现了这个 post,它介绍了另一种解决方案: