【问题标题】:Javafx save a stage/scene into a fileJavafx 将舞台/场景保存到文件中
【发布时间】:2017-05-31 14:56:26
【问题描述】:

我尝试了几种方法,包括 jaxb 和序列化。两者都没有真正起作用。舞台/场景中的nodes 包括来自richTextFX 的LabelBarChartCodeArea。对于序列化方法,我得到java.io.NotSerializableException: javafx.scene.chart.BarChart。有没有办法将场景/舞台保存到 xml 等文件(不是 FXML 只是说)?然后,即使我关闭了应用程序,我也可以恢复场景/舞台。非常感谢。

【问题讨论】:

  • 您应该考虑保存 模型(即您的应用程序正在显示的底层数据),而不是保存实际的 UI。

标签: java serialization javafx jaxb


【解决方案1】:

根据 James_D 评论,您应该保存 UI 元素中的数据,而不是元素本身,因为您已经对它们进行了编码,对吧?)

我做的方式的一个简短的sn-p:

public class SaveRestoreDemo extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        primaryStage.setTitle("Save/restore demo");
        Group root = new Group();
        Scene scene = new Scene(root, 600, 250, Color.WHITE);

        BorderPane borderPane = new BorderPane();
        borderPane.prefHeightProperty().bind(scene.heightProperty());
        borderPane.prefWidthProperty().bind(scene.widthProperty());

        VBox box = new VBox(10);
        TextArea area = new TextArea();
        area.setId("textArea");

        TextField field = new TextField();
        field.setId("field");

        box.getChildren().addAll(area, field);

        borderPane.setTop(getMainMenuContainer(box.getChildren()));
        borderPane.setCenter(box);
        root.getChildren().add(borderPane);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private VBox getMainMenuContainer(ObservableList<Node> children) {
        VBox topContainer = new VBox();
        MenuBar mainMenu = new MenuBar();
        topContainer.getChildren().add(mainMenu);
        Menu menu = new Menu("Menu");

        MenuItem load = new MenuItem("Load");
        load.setOnAction(e -> load(children));

        MenuItem save = new MenuItem("Save");
        save.setOnAction(e -> save(children));

        menu.getItems().addAll(save, load);

        mainMenu.getMenus().add(menu);
        return topContainer;
    }

    private void load(ObservableList<Node> children) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Load file");
        File file = fileChooser.showOpenDialog(new Stage());
        if (file != null) {
            try {
                Values values = new Gson().fromJson(org.apache.commons.io.FileUtils.readFileToString(file, StandardCharsets.UTF_8), Values.class);
                children.stream().filter(child -> child.getId() != null)
                        .forEach(child -> {
                            if (child instanceof TextField) {
                                TextField field = (TextField) child;
                                field.setText(values.getFieldText());
                            } else if (child instanceof TextArea) {
                                TextArea area = (TextArea) child;
                                area.setText(values.getAreaText());
                            }
                        });
            } catch (IOException e) {
                // handle properly
            }
        }
    }

    private void save(ObservableList<Node> children) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Save file");
        File file = fileChooser.showSaveDialog(new Stage());
        if (file != null) {
            Values values = new Values();
            children.stream().filter(child -> child.getId() != null)
                    .forEach(child -> {
                        if (child instanceof TextField) {
                            TextField field = (TextField) child;
                            values.setFieldText(field.getText());
                        } else if (child instanceof TextArea) {
                            TextArea area = (TextArea) child;
                            values.setAreaText(area.getText());
                        }
                    });

            try {
                org.apache.commons.io.FileUtils.write(file, new Gson().toJson(values), StandardCharsets.UTF_8);
            } catch (IOException e) {
                // handle properly
            }
        }
    }

    private static class Values {
        private String areaText;
        private String fieldText;

        public String getAreaText() {
            return areaText;
        }

        public void setAreaText(String areaText) {
            this.areaText = areaText;
        }

        public void setFieldText(String fieldText) {
            this.fieldText = fieldText;
        }

        public String getFieldText() {

            return fieldText;
        }
    }
}

基本上,我只是遍历主容器的子容器,从中收集值,然后使用 Gson 和 Apache Commons 保存到 Json。 这个例子非常简单,对于更复杂的保存\加载,您可以使用节点的 id。例如,您可以保留 id 的列表或映射,然后在保存和加载时将它们用作标识符。

【讨论】:

    猜你喜欢
    • 2016-07-17
    • 2018-07-05
    • 2020-07-02
    • 1970-01-01
    • 2016-03-06
    • 1970-01-01
    • 2021-07-21
    • 2013-09-30
    • 1970-01-01
    相关资源
    最近更新 更多