Итеративный рендеринг в FXML в нетабличном случае

#vue.js #javafx #fxml

#vue.js #javafx #fxml

Вопрос:

Каков эквивалент FXML для итеративного рендеринга ( v-for атрибута) в приведенной ниже разметке, подобной Vue?

 <VBox>
    <HBox v-for="task of tasks">
        <Checkbox :checked="task.isComplete"></Checkbox>
        <VBox>
            <Label>{{ task.title }}</Label>
            <Label>{{ task.description }}</Label>
        </VBox>
    </HBox>
</VBox>
  

Желаемое отображение:

введите описание изображения здесь

Я подготовил следующее ObservableList :

 ObservableList<Task> tasks = FXCollections.observableArrayList();
tasks.add(new Task("Wake up", "... and fly."));
tasks.add(new Task("Wash face", "... with cold water."));
  

Комментарии:

1. не поддерживается, afaik (прочитайте спецификацию fxml, чтобы убедиться)

2. @kleopatra, спасибо за комментарий. Какие альтернативы существуют?

3. Вы можете создать пользовательский компонент из HBox , а затем просто собрать их VBox в Java (не FXML).

Ответ №1:

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

 package sample;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class Main extends Application {

    static class Task{
        String title, description;
        boolean done;
        Task(String title, String description){
            this.title = title;
            this.description = description;
        }
    }

    ListView<Task> list = new ListView<>();
    ObservableList<Task> data = FXCollections.observableArrayList(
            new Task("Wake up", "... and fly."),
            new Task("Wash face", "... with cold water.")
    );

    @Override
    public void start(Stage stage) {
        VBox box = new VBox();
        Scene scene = new Scene(box, 200, 200);
        stage.setScene(scene);
        stage.setTitle("ListViewSample");
        box.getChildren().addAll(list);
        VBox.setVgrow(list, Priority.ALWAYS);
        list.setItems(data);
        list.setCellFactory(list -> new TaskCell());
        stage.show();
    }

    static class TaskCell extends ListCell<Task> {
        @Override
        public void updateItem(Task task, boolean empty) {
            super.updateItem(task, empty);
            if (task != null) {
                CheckBox done = new CheckBox();
                done.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> { task.done = !task.done; });
                done.setSelected(task.done);
                HBox cell = new HBox(
                    done,
                    new VBox(new Label(task.title), new Text(task.description))
                );
                cell.setAlignment(Pos.CENTER_LEFT);
                setGraphic(cell);
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
  

Список результатов

Смотрите Эту статью для получения более подробной информации.

Комментарии:

1. а) не создавать узлы в updateItem б) отконфигурировать ячейку, если она пуста или элемент null