将形状保存到javafx中边框窗格上绘制的文件

时间:2016-04-13 15:30:03

标签: java javafx-8

我有一个基本的应用程序,有点像玩具盒,它除了让你在屏幕上移动形状之外什么都不做,如果你双击形状,它会把它带到前台。还有一个菜单包含菜单项目" New," open"," Save" -

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.layout.BorderPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class RandCMove extends Application
{
    public static void main(String [] args)
    {
        launch(args);
    }
    public void start(Stage primaryStage)
    {
        BorderPane root = new BorderPane();

        MenuBar menuBar = new MenuBar();
        menuBar.prefWidthProperty().bind(primaryStage.widthProperty());


        Menu fileMenu = new Menu("File");
        MenuItem newMenuItem = new MenuItem("New");
        MenuItem openMenuItem = new MenuItem("Open");
        MenuItem saveMenuItem = new MenuItem("Save");
        MenuItem exitMenuItem = new MenuItem("Exit");

        fileMenu.getItems().addAll(newMenuItem,openMenuItem,saveMenuItem,
    new SeparatorMenuItem(),exitMenuItem);

        menuBar.getMenus().add(fileMenu);

        Rectangle rect = new Rectangle();
        rect.setWidth(200);
        rect.setHeight(200);
        rect.setArcHeight(20);
        rect.setArcWidth(20);
        rect.setFill(Color.RED);
        rect.setX(200);
        rect.setY(100);

        root.setTop(menuBar);
        root.getChildren().add(rect);

        Circle circle = new Circle(
            300,300,100);

        Text text = new Text(150,150,"Text");
        Font phosphate = Font.font("Phosphate",150);
        text.setFont(phosphate);

        text.setTranslateY(circle.getBoundsInParent().getMinY()+10);

        root.getChildren().add(text);

        //Positions the circle under the rectangle
        circle.setTranslateY(rect.getBoundsInParent().getMinY()+30);
        root.getChildren().add(circle);

        // Moves shapes depending on if the cursor on the particular shape
        // Brings shape to the front using double click
        root.setOnMouseMoved(e ->
         {
            if(rect.contains(e.getX(),e.getY()))
                rect.setOnMouseDragged(f ->{
                    rect.setX(f.getX());
                    rect.setY(f.getY());
                });
                rect.setOnMouseClicked(f ->{
                    if(f.getClickCount() >= 2)
                        rect.toFront();
                });
            if(circle.contains(e.getX(),e.getY()))
                    circle.setOnMouseDragged(f->{
                    circle.setCenterX(f.getX());
                    circle.setCenterY(f.getY());    
                });
                circle.setOnMouseClicked(f ->{
                    if(f.getClickCount() >= 2)
                        circle.toFront();
                });
            if(text.contains(e.getX(),e.getY()))
                text.setOnMouseDragged(f ->{
                    text.setX(f.getX());
                    text.setY(f.getY());
                  });
                text.setOnMouseClicked(f ->{
                    if(f.getClickCount() >= 2)
                        text.toFront();
                });

        });

        Scene scene = new Scene(root,600,600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

我希望能够在屏幕上保存形状的当前状态,并按下"打开"

时加载它们。

我似乎无法找到有用的东西,任何人都可以提供一些指导或指出我正确的方向吗?任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

应用程序需要首选项和配置数据以适应不同用户和环境的需求。 java.util.prefs包为应用程序提供了一种存储和检索用户和系统首选项和配置数据的方法。数据持久存储在依赖于实现的后备存储中。有两个独立的优先级节点树,一个用于用户首选项,另一个用于系统首选项。

更多信息:

http://docs.oracle.com/javase/8/docs/technotes/guides/preferences/

答案 1 :(得分:0)

这是一项非常重要的任务。我不打算在这里提供代码,但只是一般的方法大纲:

  1. 将形状序列化为FXML(您需要自己编写序列化程序代码)。
  2. 每次用户编辑形状时,再次序列化为FXML并将FXML保存为preference(如Frank Fotangs回答中所述)。
  3. 当用户首次打开应用程序时,请阅读包含当前形状的FXML的当前首选项,并使用FXMLLoader加载它们。
  4. 可以使用相同的技术来实现“打开”和“保存”菜单选项,而不是将序列化数据写入首选项,而是将其写入由FileChooser选择的文件位置。

      

    我真的更喜欢FX方式而不是Fxml。

    我认为你误解了你需要解决的问题。这样做没有“FX方式”。

    您的问题是您需要从场景图中序列化和反序列化节点,而核心JavaFX API并未提供完整的实现。

    使用JavaFX API使用JavaFX创建场景图时,它是场景的内存表示,仅在程序执行时可用。您需要做的是将该场景保存到文件中,以便在关闭应用程序时,表示场景的数据存储在某处。然后,您需要从文件中读取数据,并在用户再次启动应用程序时重新创建内存中的场景。执行此操作的唯一方法是在需要时将对象序列化为存储,并在应用程序再次启动时从存储中反序列化对象。阅读serialization上的维基百科文章,了解概念过程。

    现在您不需要使用FXML作为序列化格式,您可以使用其他格式,如JSON或YAML以及其他序列化支持库,例如Jackson。但是,对我来说,FXML似乎是最合理的格式,因为JavaFX附带了FXMLLoader,它提供了一个易于使用的API,用于将序列化数据(表示场景的FXML文件)传输到内存结构中(场景图),通过简单调用load method

    使这项任务变得棘手而不是微不足道的是,JavaFX API只附带一个FXMLLoader,它没有附带相应的类(例如FXMLSaver),它采取了内存结构的相反工作(场景图)并从中创建序列化数据(FXML文件)。所以你需要自己编写这样的逻辑。

    现在,SceneBuilder是一个开源项目,并且包含将场景图保存到FXML文件的逻辑。例如,您可以在SceneBuilder源代码中find source code for an FXMLSaver。也许您可以使用或调整该代码以将场景图形对象保存为序列化格式。在这样做时,您将不会使用场景构建器应用程序来创建和保存场景,而是您将调整SceneBuilder源代码以包含在您自己的应用程序中,这将创建并保存您的场景。