Javafx将舞台/场景保存到文件中

时间:2017-05-31 14:56:26

标签: java serialization javafx jaxb

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

1 个答案:

答案 0 :(得分:0)

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

我做的方式的简短片段:

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。 这个例子非常简单,对于更复杂的save \ loading,你可以使用节点的id。例如,您可以保留id的列表或映射,然后在保存和加载时将它们用作标识符。