Есть способ сделать это там, где у вас очень мало скрытой области действия в вашем цикле и избавиться от лишних переменных.
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 .
Если у вас есть много элементов, лучше всего их инициализировать с помощью 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);
}
}
}
Лично я предпочел бы другую возможность, но только ради полноты:
Вы также можете получить доступ к Object
s, созданному FXMLLoader
атрибутом fx:id
после загрузки, используя FXMLLoader.getNamespace()
:
<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
по умолчанию в контроллере, что означает с этим вам нужно передать информацию на контроллер самостоятельно, если это необходимо там.
Вы можете перенести свои объекты в список в 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 .