Добавление различных кнопок в ArrayList (javafx) [дубликат]

Есть способ сделать это там, где у вас очень мало скрытой области действия в вашем цикле и избавиться от лишних переменных.

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Или если вы действительно хотите получить идентификатор и действительно классический цикл for:

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Современные браузеры поддерживают методы итератора forEach, map, reduce, filter и множество других методов в прототипе Array .

0
задан Uluk Biy 16 December 2015 в 12:46
поделиться

3 ответа

Если у вас есть много элементов, лучше всего их инициализировать с помощью 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>

и контроллера

public class Controller {

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

    @FXML
    private Label label1000 ;

    // ...
}

я бы сделал

<FlowPane fx:id="container" minWidth="..." minHeight="...">
</FlowPane>

и

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);
        }
    }
}

В качестве варианта этой идеи рассмотрим определение настраиваемого компонента:

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 вы выполняете

<LabelFlow fx:id="labelFlow" numLabels="1000"/>

и в своем контроллере

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, вы может использовать отражение для доступа к переменным. Я не рекомендую это, а не только потому, что его трудно поддерживать, но также потому, что отражение по своей природе подвержено ошибкам (без проверки времени компиляции) и сложным.

Но вы могли бы сделать

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);
        }
    }
}
3
ответ дан Community 27 August 2018 в 22:22
поделиться

Лично я предпочел бы другую возможность, но только ради полноты:

Вы также можете получить доступ к Object s, созданному FXMLLoader атрибутом fx:id после загрузки, используя FXMLLoader.getNamespace() :

Пример

namespace.fxml

<AnchorPane xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <Text fx:id="node1" text="42"/>
    </children>
</AnchorPane>

Загрузка

FXMLLoader loader = new FXMLLoader(getClass().getResource("namespace.fxml"));
loader.load();
System.out.println(((Text)loader.getNamespace().get("node1")).getText());

Распечатывает текст из элемента Text в fxml (т. Е. 42).

Конечно, вы не получаете доступ к экземпляру FXMLLoader по умолчанию в контроллере, что означает с этим вам нужно передать информацию на контроллер самостоятельно, если это необходимо там.

2
ответ дан fabian 27 August 2018 в 22:22
поделиться

Вы можете перенести свои объекты в список в 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>

и получить доступ к нему в контроллере как:

@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 индивидуально, вы можете удалить fx:id s для них. Для получения дополнительной информации о функциях fxml см. Введение в FXML .

4
ответ дан Uluk Biy 27 August 2018 в 22:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: