添加FXML中定义的元素以循环列出

Vit*_*min 1 java javafx list javafx-2

我有很多具有名称a1,a2,a3,...的对象我需要将它们放入List中,因此使用它们更简单,我会以某种方式使用循环吗?

我的尝试是:

List<SomeObject> list = new LinkedList<SomeObject>();
for (int i=0; i<1000; i++){
    String varName = "a"+i;
    list.add((SomeObject) varName);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下有人有建议吗?在循环内创建变量不是解决方案,因为它们是.fxml文档的一部分.或者给我一个如何用循环创建它的建议,因为它在.fxml中创建行并行添加循环新对象.

为了更容易理解.fxml文件看起来像

  <SomeObject fx:id="a1" *other props* />
  <SomeObject fx:id="a2" *other props* />
  <SomeObject fx:id="a3" *other props* />
  <SomeObject fx:id="a4" *other props* />
Run Code Online (Sandbox Code Playgroud)

非常感谢您的建议!

Ulu*_*Biy 5

您可能更喜欢直接将对象放入 fxml 的列表中:

<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>
Run Code Online (Sandbox Code Playgroud)

并在控制器中访问它:

@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);
}
Run Code Online (Sandbox Code Playgroud)

如果您不单独访问每个 SomeObject,您可以fx:id为它们删除 s 。有关 fxml 功能的更多信息,请参阅FXML 简介


Jam*_*s_D 5

如果你有那么多项,最好用Java初始化它们,而不是使用FXML.例如,而不是:

<FlowPane fx:id="container" minWidth="..." minHeight="...">
    <Label fx:id="label1" text="Label 1"/>
    <Label fx:id="label2" text="Label 2"/>
    <Label fx:id="label3" text="Label 3"/>

    <!-- ... -->

    <Label fx:id="label1000" text="Label 1000"/>
</FlowPane>
Run Code Online (Sandbox Code Playgroud)

和一个控制器

public class Controller {

    @FXML
    private FlowPane container ;
    @FXML
    private Label label1 ;
    @FXML
    private Label label2 ;
    // ...

    @FXML
    private Label label1000 ;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

我会做

<FlowPane fx:id="container" minWidth="..." minHeight="...">
</FlowPane>
Run Code Online (Sandbox Code Playgroud)

public class Controller {

    @FXML
    private FlowPane container ;

    private List<Label> labels ;

    public void initialize() {
        labels = new ArrayList<>();
        for (int i = 1; i <= 1000; i++) {
            Label label = new Label("Label "+i);
            labels.add(label);
            container.getChildren().add(label);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

作为此想法的变体,请考虑定义自定义组件:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在用你的FXML做

<LabelFlow fx:id="labelFlow" numLabels="1000"/>
Run Code Online (Sandbox Code Playgroud)

并在你的控制器

public class Controller {
    @FXML
    private LabelFlow labelFlow ;

    public void initialize() {
        for (Label label : labelFlow.getLabels()) {
            // do whatever you need with label....
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果要在Scene Builder中使用类似自定义类,则需要跳过几个环节.请参阅向SceneBuilder 2.0添加自定义组件

如果你真的想在FXML中定义所有这些控件,这将是一个维护噩梦,你可以使用反射来访问变量.我不建议这样做,不仅因为它很难维护,而且因为它本质上的反射容易出错(没有编译时检查)而且很复杂.

但你可以做到

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)