保存用户在 JavaFX GUI 上创建的节点

Posted

技术标签:

【中文标题】保存用户在 JavaFX GUI 上创建的节点【英文标题】:saving nodes created by user on JavaFX GUI 【发布时间】:2022-01-05 05:58:17 【问题描述】:

在此处输入图像描述我在 JavaFX 上制作了一个用于创建时间表的 GUI。当我打开应用程序时,我可以将计划(按钮)添加到日列(VBox)。在我关闭应用程序后,更改不会保存:下次我打开它时,表格是空的。 我的问题是如何让它保存用户创建的节点,以便下次我打开应用程序时它们在那里?

这是添加节点的确切部分:

void ask_add_plan(ActionEvent event)
    
        Button b = (Button) event.getSource();
        VBox v = (VBox) b.getParent();

        AnchorPane pop_up = new AnchorPane(); //this pop up is to specify things about the plan 
                                              //but i removed unnecessary code for simplicity
        
        VBox pop_up_v = new VBox();

        Button add = new Button("Add");
      
        add.setOnAction(e->
            Button plan = new Button(what_to_do.getText());
           
            v.getChildren().add(plan);

            container.getChildren().remove(pop_up); //container is the anchor pane everything's in
        );

       
        pop_up_v.getChildren().add(add);

        pop_up.getChildren().add(pop_up_v);

        container.getChildren().add(pop_up); //container is the anchor pane everything's in
    

【问题讨论】:

请遵守 java 命名约定 - 至于问题:不要保存节点,而是对状态进行建模并保存模型 【参考方案1】:

JavaFX 节点只是数据的表示。他们不应该被拯救。将实际数据本身存储在类的私有字段中。

在您的Application.stop 方法中,将数据写入文件。 在您的 Application.start 方法中,读取该文件并使用它来重建 JavaFX 节点。
private static final Path PLANS_FILE =
    Path.of(System.getProperty("user.home"), "plans.txt");

private final List<String> plans = new ArrayList<>();

void ask_add_plan(ActionEvent event) 

    // ...

    add.setOnAction(e -> 
        String planText = what_to_do.getText();

        plans.add(planText);

        Button plan = new Button(planText);
        v.getChildren().add(plan);
        container.getChildren().remove(pop_up);
    );


@Override
public void start(Stage primaryStage)
throws Exception 

    // ...

    if (Files.exists(PLANS_FILE)) 
        plans.addAll(Files.readAllLines(PLANS_FILE));

        // Add UI elements for each stored plan.
        for (String planText : plans) 
            Button planButton = new Button(planText);
            v.getChildren().add(planButton);
            container.getChildren().remove(pop_up);
        
    


@Override
public void stop()
throws IOException 
    Files.write(PLANS_FILE, plans);

以上只是一个简化的例子。该文件不必只存储字符串。

我的印象是应用程序中创建的数据比计划字符串更复杂。对于复杂的数据,XML 可能是更合适的文件格式。或者您可以使用 Java 序列化。或者,您可以发明自己的文件格式。

您也不必读取和写入文件。如果您对数据库编程感到满意,您可以使用数据库。或者您可以使用Preferences(尽管首选项不太适合存储复杂数据列表)。

【讨论】:

非常感谢您的回复。这仍然不能解决我的问题。如果我在行中保存简单的东西,比如字符串和数字,那会很容易。即使在这种特殊情况下,我也可以使用一些思维和 SQL 表来做到这一点(我已经看到其中一些在搜索时被使用,但我还没有学习它们)。问题是我正在尝试通过这个来学习,并且在考虑更复杂的结构时,将数据存储为文本或表格并不是一个好的选择。例如,我添加到的 VBox 对于每个按钮都不相同,所以我也必须存储它。 我只是觉得,当我继续更复杂的结构时,如果没有系统的方法来做它会变得太复杂。 如果唯一的解决方案是使用字符串等基本数据对它们进行建模,您能否澄清每个声明的位置?我在这个项目中使用了 FXML、控制器、css 和主文件,所以我知道每个部分的确切位置。 我认为计划所属的父数据对象。但是你没有向我们展示这些,所以我只能根据你展示的内容来回答。写入纯文本文件是最简单的解决方案,但如果您的问题更复杂,则需要更复杂的解决方案。恐怕没有办法解决这个问题。如果不出意外,我希望这个答案说明 VBox 和 Buttons 不是您想要存储的东西;它们的基础数据(即模型)是。 非常感谢 VGR ig 的回答,我正在寻找一种快速解决方案,但当时不存在。非常感谢您阐明这一点并包含该代码,非常感谢【参考方案2】:

您应该使用 MVP(模型-视图-演示者)模式。在 UI 层中保存数据不是一个好习惯。使用数据创建模型,然后对其进行序列化。

【讨论】:

ig 那么没有更简单的方法了吗?我认为每次用户添加或删除某物时可能有一种方法可以编辑源文件,例如编辑 FXML。如果没有,那我就按你说的做。

以上是关于保存用户在 JavaFX GUI 上创建的节点的主要内容,如果未能解决你的问题,请参考以下文章

在java和javafx中保存应用程序设置

在 java 和 javafx 中保存应用程序设置

JavaFX FXMLLoader getController NullPointerException

如何在JavaFX中保存/加载TableView中的数据

如何制作 Javafx 图像裁剪应用程序

JavaFX - 如何保存用户设置/配置?