I'm got this error (java.io.NotSerializableException: javafx.scene.control.TreeView) when trying to save my TreeView using ObjectOutputStream.
I have 2 classes which implements Serializable and 1 main class which doesn't implements Serializable.
The 2 classes are Vendor and Address. Vendor class contain 4 variables (name, age, gender, address of Address class type), constructor which uses the set method to set all the variables, constructor which uses the set method to set the name variable only, and get/set method for the variables.
Address class contain 2 variables (street name and postal code), default constructor which uses the set method to set the variables, and get/set method for the variables.
This is my main class
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.VBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class SimpleTreeView extends Application {
private TreeView<Vendor> treeView;
public void start(Stage stage) {
stage.setTitle("Simple TreeView");
treeView = new TreeView<>();
TreeItem<Vendor> root = new TreeItem<>(new Vendor("Root"));
root.setExpanded(true);
treeView.setRoot(root);
treeView.setShowRoot(false);
TreeItem<Vendor> start = new TreeItem<>(new Vendor("Start"));
root.getChildren().add(start);
Button saveButton = new Button("Save");
saveButton.setOnMouseClicked(event -> saveTreeView(stage));
VBox vBox = new VBox(20);
vBox.getChildren().addAll(treeView, saveButton);
stage.setScene(new Scene(vBox));
stage.show();
}
private void saveTreeView(Stage stage) {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Save");
File file = fileChooser.showSaveDialog(stage);
if (file != null) {
try {
ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
os.writeObject(treeView);
os.close();
}
catch (Exception e) {
System.out.println(e);
}
}
}
public static void main(String[] args) {
launch(args);
}
}
Nodes cannot be serialized (except possibly for custom ones you implemented youself) there are too many internal states that would be too complex to restore. Lacking the possiblity to add methods/interfaces to nodes (without extending them) makes it impossible to add the
Serializableinterface and add the methods to save those parts of the data that are needed to restore the state and read this data properly.You're best of creating a serializable wrapper class that allows you to restore the properties you're actually interested in. Imho it's best not to try to serialize nodes; Create a new node when loading the data and fill it with the data loaded.
The following example shows how you could do this with
TreeItem<? extends Serializable>; There is data missing such as the expanded properties, but you should be able to restore thevalueproperty and the children. (The implementation is a bit more complex than needed forTreeItemstructures with small depth, but certain depths you need to be aware that a simpler recursive approach could lead toStackOverflowErrors.)In this case every item is serialized by writing the number of children, it's own value property and then doing the same with every child. This results in a sequence of int and value pairs that can be used to restore the data:
For an description of how
readObject,readResolveandwriteObjectwork, refer to the javadoc ofSerializable