增添绘画元素的缩放功能,提示框和提示输入框中文化

This commit is contained in:
2025-11-24 14:55:33 +08:00
parent fbb84fe16b
commit 8a7d69df94
6 changed files with 181 additions and 26 deletions
@@ -1,5 +1,7 @@
package dev.bytevibe.hyperpoint;
import dev.bytevibe.hyperpoint.Utils.MyAlert;
import dev.bytevibe.hyperpoint.Utils.MyTextInputDialog;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
@@ -15,7 +17,7 @@ import java.util.ResourceBundle;
public class Controller implements Initializable {
@FXML
private Button openSlideButton;
private Button newSlideButton;
@FXML
private Button newPageButton;
@FXML
@@ -71,12 +73,12 @@ public class Controller implements Initializable {
}
/**
* 打开幻灯片按钮的事件处理
* 新建幻灯片按钮的事件处理
*/
@FXML
public void onOpenSlide(ActionEvent actionEvent) {
TextInputDialog dialog = new TextInputDialog("我的幻灯片");
dialog.setTitle("打开/创建幻灯片");
public void onNewSlide(ActionEvent actionEvent) {
MyTextInputDialog dialog = new MyTextInputDialog("我的幻灯片");
dialog.setTitle("创建幻灯片");
dialog.setHeaderText("请输入幻灯片名称");
dialog.setContentText("幻灯片名称:");
@@ -86,10 +88,14 @@ public class Controller implements Initializable {
currentSlide = new Slide(slideName);
loadSlidePages();
Alert alert = new Alert(Alert.AlertType.INFORMATION);
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
alert.setTitle("成功");
alert.setHeaderText("幻灯片已打开");
alert.setContentText("幻灯片 \"" + slideName + "\"打开,共包含 " + currentSlide.getPages().size() + " 个页面");
alert.setHeaderText("幻灯片已创建");
alert.setContentText("幻灯片 \"" + slideName + "\"创建");
stage = (Stage) newSlideButton.getScene().getWindow();
if (stage != null) {
stage.setTitle("Hyperpoint - " + slideName);
}
alert.showAndWait();
}
}
@@ -155,7 +161,7 @@ public class Controller implements Initializable {
return;
}
TextInputDialog dialog = new TextInputDialog("页面 " + (currentSlide.getPages().size() + 1));
MyTextInputDialog dialog = new MyTextInputDialog("页面 " + (currentSlide.getPages().size() + 1));
dialog.setTitle("新建页面");
dialog.setHeaderText("请输入页面名称");
dialog.setContentText("页面名称:");
@@ -169,7 +175,7 @@ public class Controller implements Initializable {
pageListView.refresh();
pageListView.getSelectionModel().selectLast();
Alert alert = new Alert(Alert.AlertType.INFORMATION);
MyAlert alert = new MyAlert(Alert.AlertType.INFORMATION);
alert.setTitle("成功");
alert.setHeaderText("页面已创建");
alert.setContentText("新页面 \"" + pageName + "\" 已添加。");
@@ -327,15 +333,12 @@ public class Controller implements Initializable {
*/
@FXML
public void logout(ActionEvent actionEvent) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
MyAlert alert = new MyAlert(Alert.AlertType.CONFIRMATION);
alert.setTitle("退出");
alert.setHeaderText("您确定要退出吗?");
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.close();
}
@@ -14,12 +14,22 @@ import javafx.scene.text.FontWeight;
* 绘图Canvas组件,用于渲染和交互所有可绘制对象
*/
public class DrawingCanvas extends Pane {
// 缩放点的枚举
enum ResizePoint {
TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, NONE
}
private Canvas canvas;
private PageContent pageContent;
private DrawableObject selectedObject;
private double lastX, lastY;
private Runnable onSelectionChanged;
// 缩放点有关的属性
private ResizePoint resizePoint = ResizePoint.NONE;
// 缩放点大小
private static final double HANDLE_SIZE = 8;
public DrawingCanvas(PageContent pageContent) {
this.pageContent = pageContent;
this.canvas = new Canvas();
@@ -54,10 +64,21 @@ public class DrawingCanvas extends Pane {
lastX = event.getX();
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);
// 如果点击在已选中对象上,保持选中状态
if (clicked == null) {
setSelectedObject(null);
} else {
@@ -67,6 +88,40 @@ public class DrawingCanvas extends Pane {
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 dy = event.getY() - lastY;
// 更新选中对象的位置
// 如果正在缩放
if (resizePoint != ResizePoint.NONE) {
resizeObject(selectedObject, dx, dy, resizePoint);
} else {
// 移动对象
selectedObject.setX(selectedObject.getX() + dx);
selectedObject.setY(selectedObject.getY() + dy);
}
lastX = event.getX();
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) {
// 可以在这里添加其他逻辑,如取消选中等
// 释放鼠标时,重置缩放模式
resizePoint = ResizePoint.NONE;
}
/**
@@ -2,6 +2,7 @@ package dev.bytevibe.hyperpoint;
import dev.bytevibe.hyperpoint.Utils.MyAlert;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
@@ -9,6 +10,7 @@ import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.ButtonBar;
import javafx.scene.control.ButtonType;
import javafx.scene.image.Image;
import javafx.stage.Stage;
public class Main extends Application {
@@ -18,6 +20,10 @@ public class Main extends Application {
Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
Scene scene = new Scene(root, 1200, 600);
stage.setScene(scene);
Image icon = new Image(getClass().getResourceAsStream("icon.png"));
stage.setTitle("Hyperpoint");
stage.getIcons().add(icon);
stage.show();
stage.setOnCloseRequest(event -> {this.logout(stage);});
@@ -29,15 +35,12 @@ public class Main extends Application {
// 窗口退出键对应的action
public void logout(Stage stage) {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
MyAlert alert = new MyAlert(Alert.AlertType.CONFIRMATION);
alert.setTitle("退出登录");
alert.setHeaderText("您确定要退出登录吗?");
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();
}
}
@@ -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>
<HBox spacing="5" style="-fx-padding: 5;">
<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="deletePageButton" mnemonicParsing="false" onAction="#onDeletePage" text="删除页面" />
<Label text=" | " />