Во-первых, просто отметим, что соотношение сторон, которое вы используете, равно 3:4
, а не 4:3
:
3:4
означает, что на каждые 3 единицы ширины приходится 4 единицы высоты.
4:3
означает, что на каждые 4 единицы ширины приходится 3 единицы высоты.
w = h / 4 * 3
рассчитывает 3:4
, а не 4:3
.
w = h / 3 * 4
или h = w / 4 * 3
вычисляет 4:3
Переходя к тому, почему ваше изменение размера нарушается, при создании Rectangle
вы указываете координаты x, y его верхнего левого угла, а также ширину и высоту:
Rectangle rectangle = new Rectangle(x, y, width, height)
Прямоугольник будет нарисован от x, y
до x + width, y + height
Компонент изменения размера вашего кода работает нормально, когда мышь перетаскивают, вы корректно обновляете x
, y
, width
и height
.
Причина, по которой применение соотношения сторон нарушает его, заключается в том, что вы обновляете width
и height
, но не обновляете x
и y
.
Допустим, пользователь выполнил изменение размера на северо-запад, и теперь у вас есть прямоугольник:
x => 10
y => 10
width => 5
height => 10
Затем вы применяете соотношение сторон w = h / 4 * 3
:
x => 10
y => 10
width => 8
height => 10
Поскольку вы рисуете из левого верхнего угла, прямоугольник теперь вырос слева направо, но вы хотите, чтобы он рос справа налево. При изменении размера в направлении Северо-запад вы всегда хотите, чтобы нижний правый угол прямоугольника оставался на том же месте. Причина, по которой этого не происходит с вашим кодом, заключается в том, что когда вы применяете соотношение сторон к ширине прямоугольника, вы не обновляете начальную точку x, y прямоугольника.
Используя приведенный выше пример, x и y должны быть обновлены следующим образом:
x => 7
y => 10
width => 8
height => 10
Вот решение, которое я придумала:
else if (getCursorState() == RESIZING) {
Point startPoint = null;
Point endPoint = null;
switch(getCursor().getType()) {
case Cursor.SW_RESIZE_CURSOR:
startPoint = new Point((int) mouse.getX(), (int) rectangle.getMinY());
endPoint = new Point((int) rectangle.getMaxX(), (int) mouse.getY());
break;
case Cursor.NW_RESIZE_CURSOR:
startPoint = new Point((int) mouse.getX(), (int) mouse.getY());
endPoint = new Point((int) rectangle.getMaxX(), (int) rectangle.getMaxY());
break;
case Cursor.NE_RESIZE_CURSOR:
startPoint = new Point((int) rectangle.getMinX(), (int) mouse.getY());
endPoint = new Point((int) mouse.getX(), (int) rectangle.getMaxY());
break;
case Cursor.SE_RESIZE_CURSOR:
startPoint = new Point((int) rectangle.getMinX(), (int) rectangle.getMinY());
endPoint = new Point((int) mouse.getX(), (int) mouse.getY());
break;
}
rectangle.setFrameFromDiagonal(startPoint, endPoint);
if (fixedRatio) {
// Calculate 3:4 aspect ratio
rectangle.height = rectangle.width / 3 * 4;
// If this is a NW or NE resize, we need to adjust the start y coordinate to account for the new height
// This keeps the bottom right corner in the same place for a NW resize
// and the bottom left corner in the same place for a NE resize
if (getCursor().getType() == Cursor.NW_RESIZE_CURSOR || getCursor().getType() == Cursor.NE_RESIZE_CURSOR) {
rectangle.y = endPoint.y - rectangle.height;
}
}
}
Поэтому, когда размер прямоугольника изменяется в северо-западном или северо-восточном направлениях и применяется соотношение сторон, я также обновляю начальную координату y прямоугольника, чтобы учесть изменение высоты.