adding elements defined in FXML to list with loop
我有很多名称为 a1、a2、a3、...的对象
我需要将它们放入列表中,以便使用它们更简单,我会以某种方式使用循环吗?
我的尝试是:
1 2 3 4 5 | List<SomeObject> list = new LinkedList<SomeObject>(); for (int i=0; i<1000; i++){ String varName ="a"+i; list.add((SomeObject) varName); } |
在这种情况下,有人有什么建议吗?
在循环内创建变量不是解决方案,因为它们是 .fxml 文档的一部分。
或者给我一个建议,如何使用循环创建它,因为它在 .fxml 中创建与添加循环新对象平行的行。
为了更容易理解,.fxml 文件看起来像
1 2 3 4 | <SomeObject fx:id="a1" *other props* /> <SomeObject fx:id="a2" *other props* /> <SomeObject fx:id="a3" *other props* /> <SomeObject fx:id="a4" *other props* /> |
非常感谢您的建议!
如果您有这么多项目,最好使用 Java 来初始化它们,而不是使用 FXML。例如,代替:
1 2 3 4 5 6 7 8 9 |
和一个控制器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
我愿意
1 2 | <FlowPane fx:id="container" minWidth="..." minHeight="..."> </FlowPane> |
和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
作为这个想法的变体,考虑定义一个自定义组件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public class LabelFlow extends FlowPane { private List<Label> labels ; public LabelFlow(@NamedArg("numLabels") int numLabels) { labels = new ArrayList<>(); for(int i = 1 ; i <= numLabels ; i++) { Label label = new Label("Label"+i); labels.add(label); } getChildren().addAll(labels); } public List<Label> getLabels() { return Collections.unmodifiableList(labels); } } |
现在在你的 FXML 中你做
1 | <LabelFlow fx:id="labelFlow" numLabels="1000"/> |
在你的控制器中
1 2 3 4 5 6 7 8 9 10 | public class Controller { @FXML private LabelFlow labelFlow ; public void initialize() { for (Label label : labelFlow.getLabels()) { // do whatever you need with label.... } } } |
如果您想在 Scene Builder 中使用类似的自定义类,您需要跳过几个环节。请参阅将自定义组件添加到 SceneBuilder 2.0
如果您真的想在 FXML 中定义所有这些控件,这将是 imo 维护的噩梦,您可以使用反射来访问变量。我不推荐这个,不仅因为它难以维护,还因为反射本质上容易出错(没有编译时检查)和复杂。
但你可以做到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public class Controller { @FXML private FlowPane container ; @FXML private Label label1 ; @FXML private Label label2 ; // ... @FXML private Label label1000 ; private List<Label> labels ; public void initialize() throws Exception { labels = new ArrayList<>(); for (int i = 1; i <= 1000; i++) { Field field = getClass().getDeclaredField("label"+i); boolean wasAccessible = field.isAccessible(); field.setAccessible(true); Label label = (Label) field.get(this); field.setAccessible(wasAccessible); labels.add(label); } } } |
您可能更喜欢将对象直接放入 fxml 中的列表中:
1 2 3 4 5 6 7 8 | <fx:define> <FXCollections fx:id="theList" fx:factory="observableArrayList"> <SomeObject someProperty="SomeValue 1" /> <SomeObject someProperty="SomeValue 2" /> <SomeObject someProperty="SomeValue 3" /> <SomeObject someProperty="SomeValue 4" /> </FXCollections> </fx:define> |
并在控制器中访问它:
1 2 3 4 5 6 7 8 9 | @FXML private ObservableList<SomeObject> theList; @Override public void initialize( URL url, ResourceBundle rb ) { // do whatever with the list System.out.println("the list of some objects =" + theList); } |
如果您不单独访问每个 SomeObject,您可以为它们删除
我个人更喜欢另一种可能性,但只是为了完整性:
你也可以在加载后通过
例子
命名空间.fxml
1 2 3 4 5 | <AnchorPane xmlns:fx="http://javafx.com/fxml/1"> <children> <Text fx:id="node1" text="42"/> </children> </AnchorPane> |
正在加载
1 2 3 | FXMLLoader loader = new FXMLLoader(getClass().getResource("namespace.fxml")); loader.load(); System.out.println(((Text)loader.getNamespace().get("node1")).getText()); |
从 fxml 中的
当然,默认情况下,您无法访问控制器中的