feature:实现了文件的保存和读取
This commit is contained in:
@@ -27,6 +27,13 @@
|
||||
<version>${javafx.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Gson库,用于JSON序列化 -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.10.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
|
||||
@@ -46,6 +46,10 @@ public class Controller implements Initializable {
|
||||
private VBox propertyPanelContainer;
|
||||
@FXML
|
||||
private AnchorPane scenePane;
|
||||
@FXML
|
||||
private Button openSlideButton; // 添加打开幻灯片按钮
|
||||
@FXML
|
||||
private Button saveSlideButton; // 添加保存幻灯片按钮
|
||||
|
||||
private Slide currentSlide;
|
||||
private DrawingCanvas drawingCanvas;
|
||||
@@ -346,6 +350,86 @@ public class Controller implements Initializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开幻灯片文件
|
||||
*/
|
||||
@FXML
|
||||
public void onOpenSlideFile(ActionEvent actionEvent) {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("打开幻灯片");
|
||||
fileChooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("幻灯片文件 (*.hyperpoint)", "*.hyperpoint"),
|
||||
new FileChooser.ExtensionFilter("所有文件", "*.*")
|
||||
);
|
||||
|
||||
stage = (Stage) openSlideButton.getScene().getWindow();
|
||||
File file = fileChooser.showOpenDialog(stage);
|
||||
|
||||
if (file != null) {
|
||||
try {
|
||||
Presentation presentation = JsonSerializationUtil.loadFromJson(file);
|
||||
currentSlide = presentation.getSlides().isEmpty() ? null : presentation.getSlides().get(0);
|
||||
|
||||
if (currentSlide != null) {
|
||||
loadSlidePages();
|
||||
stage.setTitle("Hyperpoint - " + presentation.getName());
|
||||
|
||||
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle("成功");
|
||||
alert.setHeaderText("幻灯片已打开");
|
||||
alert.setContentText("幻灯片 \"" + presentation.getName() + "\" 已成功加载,包含 " + currentSlide.getPages().size() + " 个页面。");
|
||||
alert.showAndWait();
|
||||
} else {
|
||||
showWarning("加载失败", "幻灯片中没有找到任何页面。");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
showWarning("错误", "无法加载幻灯片文件: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存幻灯片文件
|
||||
*/
|
||||
@FXML
|
||||
public void onSaveSlide(ActionEvent actionEvent) {
|
||||
if (currentSlide == null) {
|
||||
showWarning("无幻灯片", "请先创建或打开一个幻灯片。");
|
||||
return;
|
||||
}
|
||||
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("保存幻灯片");
|
||||
fileChooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("幻灯片文件", "*.hyperpoint"),
|
||||
new FileChooser.ExtensionFilter("所有文件", "*.*")
|
||||
);
|
||||
fileChooser.setInitialFileName(currentSlide.getName() + ".hyperpoint");
|
||||
|
||||
stage = (Stage) saveSlideButton.getScene().getWindow();
|
||||
File file = fileChooser.showSaveDialog(stage);
|
||||
|
||||
if (file != null) {
|
||||
try {
|
||||
// 创建临时演示文稿对象用于保存
|
||||
Presentation tempPresentation = new Presentation(currentSlide.getName());
|
||||
tempPresentation.addSlide(currentSlide);
|
||||
|
||||
JsonSerializationUtil.saveToJson(tempPresentation, file);
|
||||
|
||||
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle("成功");
|
||||
alert.setHeaderText("幻灯片已保存");
|
||||
alert.setContentText("幻灯片已保存到: " + file.getAbsolutePath());
|
||||
alert.showAndWait();
|
||||
} catch (Exception e) {
|
||||
showWarning("错误", "无法保存幻灯片文件: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示警告对话框
|
||||
*/
|
||||
@@ -357,4 +441,3 @@ public class Controller implements Initializable {
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,10 @@ public abstract class DrawableObject implements Serializable {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public boolean isSelected() {
|
||||
return selected;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
package dev.bytevibe.hyperpoint;
|
||||
|
||||
import com.google.gson.*;
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* JSON序列化工具,用于将演示文稿保存和加载为JSON格式
|
||||
*/
|
||||
public class JsonSerializationUtil {
|
||||
private static final Gson gson = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
/**
|
||||
* 将演示文稿保存为JSON文件
|
||||
*/
|
||||
public static void saveToJson(Presentation presentation, File file) throws IOException {
|
||||
JsonObject root = new JsonObject();
|
||||
|
||||
// 保存演示文稿基本信息
|
||||
root.addProperty("name", presentation.getName());
|
||||
|
||||
// 保存所有幻灯片
|
||||
JsonArray slidesArray = new JsonArray();
|
||||
for (Slide slide : presentation.getSlides()) {
|
||||
slidesArray.add(serializeSlide(slide));
|
||||
}
|
||||
root.add("slides", slidesArray);
|
||||
|
||||
// 写入文件
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
gson.toJson(root, writer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从JSON文件加载演示文稿
|
||||
*/
|
||||
public static Presentation loadFromJson(File file) throws IOException {
|
||||
// 读取文件
|
||||
String jsonContent;
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
jsonContent = new String(new byte[]{});
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
while ((c = reader.read()) != -1) {
|
||||
sb.append((char) c);
|
||||
}
|
||||
jsonContent = sb.toString();
|
||||
}
|
||||
|
||||
// 解析JSON
|
||||
JsonObject root = JsonParser.parseString(jsonContent).getAsJsonObject();
|
||||
String name = root.get("name").getAsString();
|
||||
Presentation presentation = new Presentation(name);
|
||||
|
||||
// 加载所有幻灯片
|
||||
JsonArray slidesArray = root.getAsJsonArray("slides");
|
||||
for (JsonElement slideElement : slidesArray) {
|
||||
presentation.addSlide(deserializeSlide(slideElement.getAsJsonObject()));
|
||||
}
|
||||
|
||||
return presentation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化幻灯片
|
||||
*/
|
||||
private static JsonObject serializeSlide(Slide slide) {
|
||||
JsonObject slideObj = new JsonObject();
|
||||
slideObj.addProperty("id", slide.getId());
|
||||
slideObj.addProperty("name", slide.getName());
|
||||
|
||||
// 序列化所有页面
|
||||
JsonArray pagesArray = new JsonArray();
|
||||
for (SlidePage page : slide.getPages()) {
|
||||
pagesArray.add(serializePage(page));
|
||||
}
|
||||
slideObj.add("pages", pagesArray);
|
||||
|
||||
return slideObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化幻灯片
|
||||
*/
|
||||
private static Slide deserializeSlide(JsonObject slideObj) {
|
||||
String name = slideObj.get("name").getAsString();
|
||||
Slide slide = new Slide(name);
|
||||
|
||||
// 清除默认页面
|
||||
slide.getPages().clear();
|
||||
|
||||
// 加载所有页面
|
||||
JsonArray pagesArray = slideObj.getAsJsonArray("pages");
|
||||
for (JsonElement pageElement : pagesArray) {
|
||||
slide.getPages().add(deserializePage(pageElement.getAsJsonObject()));
|
||||
}
|
||||
|
||||
return slide;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化页面
|
||||
*/
|
||||
private static JsonObject serializePage(SlidePage page) {
|
||||
JsonObject pageObj = new JsonObject();
|
||||
pageObj.addProperty("id", page.getId());
|
||||
pageObj.addProperty("title", page.getTitle());
|
||||
pageObj.addProperty("content", page.getContent());
|
||||
|
||||
// 序列化页面中的所有可绘制对象
|
||||
JsonArray objectsArray = new JsonArray();
|
||||
for (DrawableObject obj : page.getPageContent().getDrawableObjects()) {
|
||||
objectsArray.add(serializeDrawableObject(obj));
|
||||
}
|
||||
pageObj.add("objects", objectsArray);
|
||||
|
||||
return pageObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化页面
|
||||
*/
|
||||
private static SlidePage deserializePage(JsonObject pageObj) {
|
||||
String id = pageObj.get("id").getAsString();
|
||||
String title = pageObj.get("title").getAsString();
|
||||
String content = pageObj.has("content") ? pageObj.get("content").getAsString() : "";
|
||||
|
||||
SlidePage page = new SlidePage(title);
|
||||
page.setId(id);
|
||||
page.setContent(content);
|
||||
|
||||
// 加载所有可绘制对象
|
||||
if (pageObj.has("objects")) {
|
||||
JsonArray objectsArray = pageObj.getAsJsonArray("objects");
|
||||
for (JsonElement objElement : objectsArray) {
|
||||
DrawableObject obj = deserializeDrawableObject(objElement.getAsJsonObject());
|
||||
if (obj != null) {
|
||||
page.getPageContent().addObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* 序列化可绘制对象
|
||||
*/
|
||||
private static JsonObject serializeDrawableObject(DrawableObject obj) {
|
||||
JsonObject objJson = new JsonObject();
|
||||
|
||||
objJson.addProperty("id", obj.getId());
|
||||
objJson.addProperty("x", obj.getX());
|
||||
objJson.addProperty("y", obj.getY());
|
||||
objJson.addProperty("width", obj.getWidth());
|
||||
objJson.addProperty("height", obj.getHeight());
|
||||
objJson.addProperty("type", obj.getTypeName());
|
||||
|
||||
if (obj instanceof TextObject) {
|
||||
TextObject textObj = (TextObject) obj;
|
||||
objJson.addProperty("text", textObj.getText());
|
||||
objJson.addProperty("fontFamily", textObj.getFontFamily());
|
||||
objJson.addProperty("fontSize", textObj.getFontSize());
|
||||
objJson.addProperty("fontStyle", textObj.getFontStyle());
|
||||
objJson.addProperty("textColor", textObj.getTextColor());
|
||||
|
||||
} else if (obj instanceof ShapeObject) {
|
||||
ShapeObject shapeObj = (ShapeObject) obj;
|
||||
objJson.addProperty("shapeType", shapeObj.getShapeType().name());
|
||||
objJson.addProperty("fillColor", shapeObj.getFillColor());
|
||||
objJson.addProperty("strokeColor", shapeObj.getStrokeColor());
|
||||
objJson.addProperty("strokeWidth", shapeObj.getStrokeWidth());
|
||||
|
||||
} else if (obj instanceof ImageObject) {
|
||||
ImageObject imgObj = (ImageObject) obj;
|
||||
objJson.addProperty("imagePath", imgObj.getImagePath());
|
||||
}
|
||||
|
||||
return objJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 反序列化可绘制对象
|
||||
*/
|
||||
private static DrawableObject deserializeDrawableObject(JsonObject objJson) {
|
||||
String type = objJson.get("type").getAsString();
|
||||
double x = objJson.get("x").getAsDouble();
|
||||
double y = objJson.get("y").getAsDouble();
|
||||
double width = objJson.get("width").getAsDouble();
|
||||
double height = objJson.get("height").getAsDouble();
|
||||
String id = objJson.get("id").getAsString();
|
||||
|
||||
DrawableObject obj = null;
|
||||
|
||||
if (type.equals("Text")) {
|
||||
String text = objJson.get("text").getAsString();
|
||||
obj = new TextObject(x, y, text);
|
||||
obj.setWidth(width);
|
||||
obj.setHeight(height);
|
||||
|
||||
TextObject textObj = (TextObject) obj;
|
||||
if (objJson.has("fontFamily")) {
|
||||
textObj.setFontFamily(objJson.get("fontFamily").getAsString());
|
||||
}
|
||||
if (objJson.has("fontSize")) {
|
||||
textObj.setFontSize(objJson.get("fontSize").getAsDouble());
|
||||
}
|
||||
if (objJson.has("fontStyle")) {
|
||||
textObj.setFontStyle(objJson.get("fontStyle").getAsString());
|
||||
}
|
||||
if (objJson.has("textColor")) {
|
||||
textObj.setTextColor(objJson.get("textColor").getAsString());
|
||||
}
|
||||
|
||||
} else if (type.startsWith("Shape_")) {
|
||||
String shapeTypeStr = type.replace("Shape_", "");
|
||||
ShapeObject.ShapeType shapeType = ShapeObject.ShapeType.valueOf(shapeTypeStr);
|
||||
obj = new ShapeObject(x, y, width, height, shapeType);
|
||||
|
||||
ShapeObject shapeObj = (ShapeObject) obj;
|
||||
if (objJson.has("fillColor")) {
|
||||
shapeObj.setFillColor(objJson.get("fillColor").getAsString());
|
||||
}
|
||||
if (objJson.has("strokeColor")) {
|
||||
shapeObj.setStrokeColor(objJson.get("strokeColor").getAsString());
|
||||
}
|
||||
if (objJson.has("strokeWidth")) {
|
||||
shapeObj.setStrokeWidth(objJson.get("strokeWidth").getAsDouble());
|
||||
}
|
||||
|
||||
} else if (type.equals("Image")) {
|
||||
String imagePath = objJson.get("imagePath").getAsString();
|
||||
obj = new ImageObject(x, y, width, height, imagePath);
|
||||
}
|
||||
|
||||
if (obj != null) {
|
||||
obj.setId(id);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ module dev.bytevibe.hyperpoint {
|
||||
requires javafx.controls;
|
||||
requires javafx.fxml;
|
||||
requires java.desktop;
|
||||
requires com.google.gson;
|
||||
|
||||
|
||||
opens dev.bytevibe.hyperpoint to javafx.fxml;
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
<HBox spacing="5" style="-fx-padding: 5;">
|
||||
<children>
|
||||
<Button fx:id="newSlideButton" mnemonicParsing="false" onAction="#onNewSlide" text="新建幻灯片" />
|
||||
<Button mnemonicParsing="false" text="打开幻灯片" />
|
||||
<Button fx:id="openSlideButton" mnemonicParsing="false" onAction="#onOpenSlideFile" text="打开幻灯片" />
|
||||
<Button fx:id="newPageButton" mnemonicParsing="false" onAction="#onNewPage" text="新建页面" />
|
||||
<Button fx:id="deletePageButton" mnemonicParsing="false" onAction="#onDeletePage" text="删除页面" />
|
||||
<Button mnemonicParsing="false" text="保存幻灯片" />
|
||||
<Button fx:id="saveSlideButton" mnemonicParsing="false" onAction="#onSaveSlide" text="保存幻灯片" />
|
||||
<Label text=" | " />
|
||||
<Button fx:id="addTextButton" mnemonicParsing="false" onAction="#onAddText" text="添加文本" />
|
||||
<Button fx:id="addLineButton" mnemonicParsing="false" onAction="#onAddLine" text="直线" />
|
||||
|
||||
Reference in New Issue
Block a user