增添绘画元素的缩放功能,提示框和提示输入框中文化
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
package dev.bytevibe.hyperpoint;
|
package dev.bytevibe.hyperpoint;
|
||||||
|
|
||||||
|
import dev.bytevibe.hyperpoint.Utils.MyAlert;
|
||||||
|
import dev.bytevibe.hyperpoint.Utils.MyTextInputDialog;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.Initializable;
|
import javafx.fxml.Initializable;
|
||||||
@@ -15,7 +17,7 @@ import java.util.ResourceBundle;
|
|||||||
|
|
||||||
public class Controller implements Initializable {
|
public class Controller implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
private Button openSlideButton;
|
private Button newSlideButton;
|
||||||
@FXML
|
@FXML
|
||||||
private Button newPageButton;
|
private Button newPageButton;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -71,12 +73,12 @@ public class Controller implements Initializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开幻灯片按钮的事件处理
|
* 新建幻灯片按钮的事件处理
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
public void onOpenSlide(ActionEvent actionEvent) {
|
public void onNewSlide(ActionEvent actionEvent) {
|
||||||
TextInputDialog dialog = new TextInputDialog("我的幻灯片");
|
MyTextInputDialog dialog = new MyTextInputDialog("我的幻灯片");
|
||||||
dialog.setTitle("打开/创建幻灯片");
|
dialog.setTitle("创建幻灯片");
|
||||||
dialog.setHeaderText("请输入幻灯片名称");
|
dialog.setHeaderText("请输入幻灯片名称");
|
||||||
dialog.setContentText("幻灯片名称:");
|
dialog.setContentText("幻灯片名称:");
|
||||||
|
|
||||||
@@ -86,10 +88,14 @@ public class Controller implements Initializable {
|
|||||||
currentSlide = new Slide(slideName);
|
currentSlide = new Slide(slideName);
|
||||||
loadSlidePages();
|
loadSlidePages();
|
||||||
|
|
||||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
|
||||||
alert.setTitle("成功");
|
alert.setTitle("成功");
|
||||||
alert.setHeaderText("幻灯片已打开");
|
alert.setHeaderText("幻灯片已创建");
|
||||||
alert.setContentText("幻灯片 \"" + slideName + "\" 已打开,共包含 " + currentSlide.getPages().size() + " 个页面。");
|
alert.setContentText("幻灯片 \"" + slideName + "\" 已创建。");
|
||||||
|
stage = (Stage) newSlideButton.getScene().getWindow();
|
||||||
|
if (stage != null) {
|
||||||
|
stage.setTitle("Hyperpoint - " + slideName);
|
||||||
|
}
|
||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +161,7 @@ public class Controller implements Initializable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextInputDialog dialog = new TextInputDialog("页面 " + (currentSlide.getPages().size() + 1));
|
MyTextInputDialog dialog = new MyTextInputDialog("页面 " + (currentSlide.getPages().size() + 1));
|
||||||
dialog.setTitle("新建页面");
|
dialog.setTitle("新建页面");
|
||||||
dialog.setHeaderText("请输入页面名称");
|
dialog.setHeaderText("请输入页面名称");
|
||||||
dialog.setContentText("页面名称:");
|
dialog.setContentText("页面名称:");
|
||||||
@@ -169,7 +175,7 @@ public class Controller implements Initializable {
|
|||||||
pageListView.refresh();
|
pageListView.refresh();
|
||||||
pageListView.getSelectionModel().selectLast();
|
pageListView.getSelectionModel().selectLast();
|
||||||
|
|
||||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
|
||||||
alert.setTitle("成功");
|
alert.setTitle("成功");
|
||||||
alert.setHeaderText("页面已创建");
|
alert.setHeaderText("页面已创建");
|
||||||
alert.setContentText("新页面 \"" + pageName + "\" 已添加。");
|
alert.setContentText("新页面 \"" + pageName + "\" 已添加。");
|
||||||
@@ -327,15 +333,12 @@ public class Controller implements Initializable {
|
|||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
public void logout(ActionEvent actionEvent) {
|
public void logout(ActionEvent actionEvent) {
|
||||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
MyAlert alert = new MyAlert(Alert.AlertType.CONFIRMATION);
|
||||||
alert.setTitle("退出");
|
alert.setTitle("退出");
|
||||||
alert.setHeaderText("您确定要退出吗?");
|
alert.setHeaderText("您确定要退出吗?");
|
||||||
alert.setContentText("点击确定退出,点击取消返回。");
|
alert.setContentText("点击确定退出,点击取消返回。");
|
||||||
ButtonType confirm = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
|
|
||||||
ButtonType cancel = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
|
|
||||||
alert.getButtonTypes().setAll(confirm, cancel);
|
|
||||||
|
|
||||||
if (alert.showAndWait().orElse(null) == confirm) {
|
if (alert.showAndWait().orElse(null) == MyAlert.isOK()) {
|
||||||
stage = (Stage) logout.getScene().getWindow();
|
stage = (Stage) logout.getScene().getWindow();
|
||||||
stage.close();
|
stage.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,12 +14,22 @@ import javafx.scene.text.FontWeight;
|
|||||||
* 绘图Canvas组件,用于渲染和交互所有可绘制对象
|
* 绘图Canvas组件,用于渲染和交互所有可绘制对象
|
||||||
*/
|
*/
|
||||||
public class DrawingCanvas extends Pane {
|
public class DrawingCanvas extends Pane {
|
||||||
|
// 缩放点的枚举
|
||||||
|
enum ResizePoint {
|
||||||
|
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, NONE
|
||||||
|
}
|
||||||
|
|
||||||
private Canvas canvas;
|
private Canvas canvas;
|
||||||
private PageContent pageContent;
|
private PageContent pageContent;
|
||||||
private DrawableObject selectedObject;
|
private DrawableObject selectedObject;
|
||||||
private double lastX, lastY;
|
private double lastX, lastY;
|
||||||
private Runnable onSelectionChanged;
|
private Runnable onSelectionChanged;
|
||||||
|
|
||||||
|
// 缩放点有关的属性
|
||||||
|
private ResizePoint resizePoint = ResizePoint.NONE;
|
||||||
|
// 缩放点大小
|
||||||
|
private static final double HANDLE_SIZE = 8;
|
||||||
|
|
||||||
public DrawingCanvas(PageContent pageContent) {
|
public DrawingCanvas(PageContent pageContent) {
|
||||||
this.pageContent = pageContent;
|
this.pageContent = pageContent;
|
||||||
this.canvas = new Canvas();
|
this.canvas = new Canvas();
|
||||||
@@ -54,10 +64,21 @@ public class DrawingCanvas extends Pane {
|
|||||||
lastX = event.getX();
|
lastX = event.getX();
|
||||||
lastY = event.getY();
|
lastY = event.getY();
|
||||||
|
|
||||||
|
// 如果已经有选中对象,先检查是否点击在调整点上
|
||||||
|
if (selectedObject != null) {
|
||||||
|
resizePoint = getResizePointAt(lastX, lastY, selectedObject);
|
||||||
|
if (resizePoint != ResizePoint.NONE) {
|
||||||
|
// 点击在调整点上,进入缩放模式
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置缩放模式
|
||||||
|
resizePoint = ResizePoint.NONE;
|
||||||
|
|
||||||
// 查找被点击的对象
|
// 查找被点击的对象
|
||||||
DrawableObject clicked = pageContent.findObjectAt(lastX, lastY);
|
DrawableObject clicked = pageContent.findObjectAt(lastX, lastY);
|
||||||
|
|
||||||
// 如果点击在已选中对象上,保持选中状态
|
|
||||||
if (clicked == null) {
|
if (clicked == null) {
|
||||||
setSelectedObject(null);
|
setSelectedObject(null);
|
||||||
} else {
|
} else {
|
||||||
@@ -67,6 +88,40 @@ public class DrawingCanvas extends Pane {
|
|||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取点击位置对应的调整点
|
||||||
|
*/
|
||||||
|
private ResizePoint getResizePointAt(double x, double y, DrawableObject obj) {
|
||||||
|
double handleSize = HANDLE_SIZE;
|
||||||
|
double objX = obj.getX();
|
||||||
|
double objY = obj.getY();
|
||||||
|
double objW = obj.getWidth();
|
||||||
|
double objH = obj.getHeight();
|
||||||
|
|
||||||
|
// 检查左上角
|
||||||
|
if (x >= objX - handleSize && x <= objX + handleSize &&
|
||||||
|
y >= objY - handleSize && y <= objY + handleSize) {
|
||||||
|
return ResizePoint.TOP_LEFT;
|
||||||
|
}
|
||||||
|
// 检查右上角
|
||||||
|
if (x >= objX + objW - handleSize && x <= objX + objW + handleSize &&
|
||||||
|
y >= objY - handleSize && y <= objY + handleSize) {
|
||||||
|
return ResizePoint.TOP_RIGHT;
|
||||||
|
}
|
||||||
|
// 检查左下角
|
||||||
|
if (x >= objX - handleSize && x <= objX + handleSize &&
|
||||||
|
y >= objY + objH - handleSize && y <= objY + objH + handleSize) {
|
||||||
|
return ResizePoint.BOTTOM_LEFT;
|
||||||
|
}
|
||||||
|
// 检查右下角
|
||||||
|
if (x >= objX + objW - handleSize && x <= objX + objW + handleSize &&
|
||||||
|
y >= objY + objH - handleSize && y <= objY + objH + handleSize) {
|
||||||
|
return ResizePoint.BOTTOM_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResizePoint.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鼠标拖动事件处理
|
* 鼠标拖动事件处理
|
||||||
*/
|
*/
|
||||||
@@ -75,9 +130,14 @@ public class DrawingCanvas extends Pane {
|
|||||||
double dx = event.getX() - lastX;
|
double dx = event.getX() - lastX;
|
||||||
double dy = event.getY() - lastY;
|
double dy = event.getY() - lastY;
|
||||||
|
|
||||||
// 更新选中对象的位置
|
// 如果正在缩放
|
||||||
selectedObject.setX(selectedObject.getX() + dx);
|
if (resizePoint != ResizePoint.NONE) {
|
||||||
selectedObject.setY(selectedObject.getY() + dy);
|
resizeObject(selectedObject, dx, dy, resizePoint);
|
||||||
|
} else {
|
||||||
|
// 移动对象
|
||||||
|
selectedObject.setX(selectedObject.getX() + dx);
|
||||||
|
selectedObject.setY(selectedObject.getY() + dy);
|
||||||
|
}
|
||||||
|
|
||||||
lastX = event.getX();
|
lastX = event.getX();
|
||||||
lastY = event.getY();
|
lastY = event.getY();
|
||||||
@@ -86,13 +146,58 @@ public class DrawingCanvas extends Pane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缩放对象
|
||||||
|
*/
|
||||||
|
private void resizeObject(DrawableObject obj, double dx, double dy, ResizePoint point) {
|
||||||
|
// 最小尺寸限制
|
||||||
|
final double MIN_SIZE = 20;
|
||||||
|
|
||||||
|
switch (point) {
|
||||||
|
case TOP_LEFT:
|
||||||
|
// 从左上角缩放:x和y增加,width和height减少
|
||||||
|
if (obj.getWidth() - dx >= MIN_SIZE && obj.getHeight() - dy >= MIN_SIZE) {
|
||||||
|
obj.setX(obj.getX() + dx);
|
||||||
|
obj.setY(obj.getY() + dy);
|
||||||
|
obj.setWidth(obj.getWidth() - dx);
|
||||||
|
obj.setHeight(obj.getHeight() - dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOP_RIGHT:
|
||||||
|
// 从右上角缩放:y增加,width增加,height减少
|
||||||
|
if (obj.getWidth() + dx >= MIN_SIZE && obj.getHeight() - dy >= MIN_SIZE) {
|
||||||
|
obj.setY(obj.getY() + dy);
|
||||||
|
obj.setWidth(obj.getWidth() + dx);
|
||||||
|
obj.setHeight(obj.getHeight() - dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BOTTOM_LEFT:
|
||||||
|
// 从左下角缩放:x增加,width减少,height增加
|
||||||
|
if (obj.getWidth() - dx >= MIN_SIZE && obj.getHeight() + dy >= MIN_SIZE) {
|
||||||
|
obj.setX(obj.getX() + dx);
|
||||||
|
obj.setWidth(obj.getWidth() - dx);
|
||||||
|
obj.setHeight(obj.getHeight() + dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BOTTOM_RIGHT:
|
||||||
|
// 从右下角缩放:width和height增加
|
||||||
|
if (obj.getWidth() + dx >= MIN_SIZE && obj.getHeight() + dy >= MIN_SIZE) {
|
||||||
|
obj.setWidth(obj.getWidth() + dx);
|
||||||
|
obj.setHeight(obj.getHeight() + dy);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鼠标释放事件处理
|
* 鼠标释放事件处理
|
||||||
*/
|
*/
|
||||||
private void handleMouseReleased(MouseEvent event) {
|
private void handleMouseReleased(MouseEvent event) {
|
||||||
// 可以在这里添加其他逻辑,如取消选中等
|
// 释放鼠标时,重置缩放模式
|
||||||
|
resizePoint = ResizePoint.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package dev.bytevibe.hyperpoint;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import dev.bytevibe.hyperpoint.Utils.MyAlert;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
import javafx.scene.Parent;
|
||||||
@@ -9,6 +10,7 @@ import javafx.scene.Scene;
|
|||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonBar;
|
import javafx.scene.control.ButtonBar;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
public class Main extends Application {
|
public class Main extends Application {
|
||||||
@@ -18,6 +20,10 @@ public class Main extends Application {
|
|||||||
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
|
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
|
||||||
Scene scene = new Scene(root, 1200, 600);
|
Scene scene = new Scene(root, 1200, 600);
|
||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
|
|
||||||
|
Image icon = new Image(getClass().getResourceAsStream("icon.png"));
|
||||||
|
stage.setTitle("Hyperpoint");
|
||||||
|
stage.getIcons().add(icon);
|
||||||
stage.show();
|
stage.show();
|
||||||
|
|
||||||
stage.setOnCloseRequest(event -> {this.logout(stage);});
|
stage.setOnCloseRequest(event -> {this.logout(stage);});
|
||||||
@@ -29,15 +35,12 @@ public class Main extends Application {
|
|||||||
// 窗口退出键对应的action
|
// 窗口退出键对应的action
|
||||||
public void logout(Stage stage) {
|
public void logout(Stage stage) {
|
||||||
|
|
||||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
MyAlert alert = new MyAlert(Alert.AlertType.CONFIRMATION);
|
||||||
alert.setTitle("退出登录");
|
alert.setTitle("退出登录");
|
||||||
alert.setHeaderText("您确定要退出登录吗?");
|
alert.setHeaderText("您确定要退出登录吗?");
|
||||||
alert.setContentText("点击确定退出登录,点击取消返回。");
|
alert.setContentText("点击确定退出登录,点击取消返回。");
|
||||||
ButtonType confirm = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
|
|
||||||
ButtonType cancel = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
|
|
||||||
alert.getButtonTypes().setAll(confirm, cancel);
|
|
||||||
|
|
||||||
if (alert.showAndWait().orElse(null) == confirm) {
|
if (alert.showAndWait().orElse(null) == MyAlert.isOK()) {
|
||||||
stage.close();
|
stage.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package dev.bytevibe.hyperpoint.Utils;
|
||||||
|
|
||||||
|
import javafx.scene.control.Alert;
|
||||||
|
import javafx.scene.control.ButtonBar;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
|
||||||
|
// 提示框,按钮设置为中文
|
||||||
|
public class MyAlert extends Alert {
|
||||||
|
private static ButtonType confirm = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
|
||||||
|
private static ButtonType cancel = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||||
|
|
||||||
|
public MyAlert(Alert.AlertType alertType) {
|
||||||
|
super(alertType);
|
||||||
|
if (alertType == Alert.AlertType.CONFIRMATION) {
|
||||||
|
getDialogPane().getButtonTypes().setAll(confirm, cancel);
|
||||||
|
} else if (alertType == Alert.AlertType.INFORMATION || alertType == Alert.AlertType.WARNING || alertType == Alert.AlertType.ERROR) {
|
||||||
|
getDialogPane().getButtonTypes().setAll(confirm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ButtonType isOK() {
|
||||||
|
return confirm;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package dev.bytevibe.hyperpoint.Utils;
|
||||||
|
|
||||||
|
import javafx.scene.control.ButtonBar;
|
||||||
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.TextInputDialog;
|
||||||
|
|
||||||
|
// 提示输入框,按钮设置为中文
|
||||||
|
public class MyTextInputDialog extends TextInputDialog {
|
||||||
|
private static ButtonType confirm = new ButtonType("确定", ButtonBar.ButtonData.OK_DONE);
|
||||||
|
private static ButtonType cancel = new ButtonType("取消", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||||
|
|
||||||
|
public MyTextInputDialog(String defaultValue) {
|
||||||
|
super(defaultValue);
|
||||||
|
getDialogPane().getButtonTypes().setAll(confirm, cancel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ButtonType isOK() {
|
||||||
|
return confirm;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<children>
|
<children>
|
||||||
<HBox spacing="5" style="-fx-padding: 5;">
|
<HBox spacing="5" style="-fx-padding: 5;">
|
||||||
<children>
|
<children>
|
||||||
<Button fx:id="openSlideButton" mnemonicParsing="false" onAction="#onOpenSlide" text="打开幻灯片" />
|
<Button fx:id="newSlideButton" mnemonicParsing="false" onAction="#onNewSlide" text="新建幻灯片" />
|
||||||
<Button fx:id="newPageButton" mnemonicParsing="false" onAction="#onNewPage" text="新建页面" />
|
<Button fx:id="newPageButton" mnemonicParsing="false" onAction="#onNewPage" text="新建页面" />
|
||||||
<Button fx:id="deletePageButton" mnemonicParsing="false" onAction="#onDeletePage" text="删除页面" />
|
<Button fx:id="deletePageButton" mnemonicParsing="false" onAction="#onDeletePage" text="删除页面" />
|
||||||
<Label text=" | " />
|
<Label text=" | " />
|
||||||
|
|||||||
Reference in New Issue
Block a user