完成矩形的八个点操作操作和移动矩形操作

This commit is contained in:
yang 2022-09-16 20:49:56 +08:00
parent 04ab07d87a
commit f0cc080a5e
2 changed files with 200 additions and 103 deletions

View File

@ -1,9 +1,9 @@
package org.rococy.roomit.control;
import javafx.beans.value.ObservableValue;
import javafx.scene.Cursor;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import org.rococy.roomit.enums.RectangleCtrl;
/**
* 能改变尺寸的矩形
@ -13,177 +13,147 @@ import javafx.scene.shape.Rectangle;
*/
public class ResizableRectangle extends Rectangle {
private double lastX, lastY;
/**
* 矩形原点
*/
private double originX, originY;
double dragStartX, dragStartY, dragOriginWidth, dragOriginHeight,
newX = 0, newY = 0, newLayoutX = -1, newLayoutY = -1, width = 0, height = 0;
/**
* 记录调整完矩形后的大小
*/
private double width, height;
private String resizeType;
/**
* 当处于移动状态时记录的xy值
*/
private double moveX, moveY;
/**
* 矩形操作类型
*/
private RectangleCtrl rectangleCtrl;
public ResizableRectangle(double x, double y) {
/**
* 配置项
*/
private static final String COLOR = "#f00";
private static final double BORDER_WIDTH = 3;
/**
* @param originX 在整个屏幕内的x值
* @param originY 在整个屏幕内的y值
*/
public ResizableRectangle(double originX, double originY) {
// 记录原点
this.originX = originX;
this.originY = originY;
// 填充透明色边框颜色边框宽度
this.setFill(Paint.valueOf("#00000000"));
this.setStroke(Paint.valueOf("#f00"));
this.setStrokeWidth(3);
this.setStroke(Paint.valueOf(COLOR));
this.setStrokeWidth(BORDER_WIDTH);
this.setCache(false);
this.widthProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
width = newValue.doubleValue();
});
this.heightProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
height = newValue.doubleValue();
});
this.xProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
newX = newValue.doubleValue();
});
this.yProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
newY = newValue.doubleValue();
});
this.layoutXProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
newLayoutX = newValue.doubleValue();
});
this.layoutYProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
newLayoutY = newValue.doubleValue();
});
this.initScaleEvents();
// 初始化调整大小事件
this.initEvents();
}
public void initScaleEvents() {
/**
* 初始化矩形调整大小事件
*/
public void initEvents() {
bindMousePressedEvent();
bindMouseMovedEvent();
bindMouseDraggedEvent();
bindMouseReleasedEvent();
}
/**
* 鼠标按下
*/
private void bindMousePressedEvent() {
this.setOnMousePressed(e -> {
dragOriginWidth = width;
dragOriginHeight = height;
width = this.getWidth();
height = this.getHeight();
this.lastX = e.getScreenX();
this.lastY = e.getScreenY();
System.out.println("startX: " + e.getScreenX() + ", startY: " + e.getScreenY());
});
this.setOnMouseReleased(e -> {
this.lastX = e.getScreenX();
this.lastY = e.getScreenY();
});
this.setOnMouseDragged(e -> {
// 防止快速操作
if (resizeType == null) {
return;
}
double endX = e.getScreenX() - lastX, endY = e.getScreenY() - lastY;
switch (resizeType) {
case "topLeft" -> {
this.setLayoutX(e.getScreenX());
this.setLayoutY(e.getScreenY());
this.setWidth(dragOriginWidth - endX);
this.setHeight(dragOriginHeight - endY);
}
case "topMiddle" -> {
if (endY > dragOriginHeight) {
this.setY(dragOriginHeight);
this.setHeight(endY - dragOriginHeight);
} else {
// 定义原点
this.setY(endY);
this.setHeight(dragOriginHeight - endY);
}
}
case "topRight" -> {
// 定义原点
this.setX(endX);
this.setY(endY);
this.setWidth(endX);
this.setHeight(dragOriginHeight - endY);
}
case "bottomRight" -> {
}
if (rectangleCtrl == RectangleCtrl.MOVE) {
moveX = e.getScreenX() - this.getLayoutX();
moveY = e.getScreenY() - this.getLayoutY();
}
});
}
/**
* 鼠标移动
*/
private void bindMouseMovedEvent() {
this.setOnMouseMoved(e -> {
double width = this.getWidth(),
height = this.getHeight(),
x = e.getX() - newX,
y = e.getY() - newY;
x = e.getScreenX() - this.getLayoutX(),
y = e.getScreenY() - this.getLayoutY();
// topLeft
if (x <= 3 && y <= 3) {
this.setCursor(Cursor.SE_RESIZE);
resizeType = "topLeft";
rectangleCtrl = RectangleCtrl.TOP_LEFT;
return;
}
// topMiddle
if (x <= width - 3 && y <= 3) {
this.setCursor(Cursor.N_RESIZE);
resizeType = "topMiddle";
rectangleCtrl = RectangleCtrl.TOP_MIDDLE;
return;
}
// topRight
if (x <= width && y <= 3) {
this.setCursor(Cursor.NE_RESIZE);
resizeType = "topRight";
rectangleCtrl = RectangleCtrl.TOP_RIGHT;
return;
}
// centerLeft
if (x <= 3 && y <= height - 3) {
this.setCursor(Cursor.W_RESIZE);
resizeType = "centerLeft";
rectangleCtrl = RectangleCtrl.CENTER_LEFT;
return;
}
// bottomLeft
if (x <= 3 && y <= height) {
this.setCursor(Cursor.NE_RESIZE);
resizeType = "bottomLeft";
rectangleCtrl = RectangleCtrl.BOTTOM_LEFT;
return;
}
// bottomMiddle
if (x <= width - 3 && y >= height - 3) {
this.setCursor(Cursor.N_RESIZE);
resizeType = "bottomMiddle";
rectangleCtrl = RectangleCtrl.BOTTOM_MIDDLE;
return;
}
// bottomRight
if (x <= width && y >= height - 3) {
this.setCursor(Cursor.SE_RESIZE);
resizeType = "bottomRight";
rectangleCtrl = RectangleCtrl.BOTTOM_RIGHT;
return;
}
// centerRight
if (x >= width - 3 && y <= height) {
this.setCursor(Cursor.W_RESIZE);
resizeType = "centerRight";
rectangleCtrl = RectangleCtrl.CENTER_RIGHT;
return;
}
// 移动指针
if (x >= 3 + 1 && x <= width - 3 && y >= 3 + 1 && y <= height - 3) {
this.setCursor(Cursor.MOVE);
resizeType = "move";
rectangleCtrl = RectangleCtrl.MOVE;
return;
}
@ -191,8 +161,79 @@ public class ResizableRectangle extends Rectangle {
});
}
@Override
public boolean isResizable() {
return true;
/**
* 鼠标拖拽
*/
private void bindMouseDraggedEvent() {
this.setOnMouseDragged(e -> {
// 防止快速操作
if (rectangleCtrl == null) {
return;
}
double screenX = e.getScreenX(),
screenY = e.getScreenY(),
x = screenX - originX,
y = screenY - originY;
switch (rectangleCtrl) {
case TOP_LEFT -> {
this.setLayoutX(screenX);
this.setLayoutY(screenY);
this.setWidth(width - x);
this.setHeight(height - y);
}
case TOP_MIDDLE -> {
this.setLayoutY(screenY);
this.setHeight(height - y);
}
case TOP_RIGHT -> {
this.setLayoutY(screenY);
this.setWidth(x);
this.setHeight(height - y);
}
case CENTER_LEFT -> {
this.setLayoutX(screenX);
this.setWidth(width - x);
}
case CENTER_RIGHT -> this.setWidth(x);
case BOTTOM_LEFT -> {
this.setLayoutX(screenX);
this.setWidth(width - x);
this.setHeight(y);
}
case BOTTOM_MIDDLE -> this.setHeight(y);
case BOTTOM_RIGHT -> {
this.setWidth(x);
this.setHeight(y);
}
case MOVE -> {
this.setLayoutX(screenX - moveX);
this.setLayoutY(screenY - moveY);
}
}
});
}
/**
* 鼠标抬起
*/
private void bindMouseReleasedEvent() {
this.setOnMouseReleased(e -> {
this.originX = this.getLayoutX();
this.originY = this.getLayoutY();
});
}
}

View File

@ -0,0 +1,56 @@
package org.rococy.roomit.enums;
/**
* Shape的八个调整大小的点位
*
* @author Rococy
* @date 2022/9/16
*/
public enum RectangleCtrl {
/**
* 上左缩放
*/
TOP_LEFT,
/**
* 上中缩放
*/
TOP_MIDDLE,
/**
* 上右缩放
*/
TOP_RIGHT,
/**
* 中左缩放
*/
CENTER_LEFT,
/**
* 中右缩放
*/
CENTER_RIGHT,
/**
* 下左缩放
*/
BOTTOM_LEFT,
/**
* 下中缩放
*/
BOTTOM_MIDDLE,
/**
* 下右缩放
*/
BOTTOM_RIGHT,
/**
* 移动
*/
MOVE
}