英文:
can't resize and set location of JFrame in the same time
问题
我尝试进行一些训练项目,在其中我添加了一个没有装饰的JFrame,然后我为它添加了MouseMotionListener以改变鼠标光标,然后改变它的大小和位置,以使其看起来像任何可调整大小的有装饰的JFrame。
问题:在北部和西部,窗口框架没有被调整大小,而是持续改变位置而不改变大小,但当我以调试模式运行程序时,它可以正常工作。
我尝试使用线程和setBounds代替setSize,还尝试添加frame.revalidate()和frame.repaint(),但都没有奏效,有什么建议吗?
谢谢你的时间。
英文:
I was trying to do some projects for traning, in this one I added an undecorated JFrame, so I added MouseMotionListener to it to change the mouse cursor then change it's size and location to look like any resizable decorated JFrame
pblm: at north and west the frame doesn't resized it keeps change location without change it's size, but when I run the program in the debug mode it works
I tried use threads and setBounds instead of setSize, i tried also to add frame.revalidate() and frame.repaint(), but nothing work, any suggesion
thank you for your time
package newpackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
public class ResizeUndecoratedJFrame {
private int oldCursPosX;
private int oldCursPosY;
private Dimension lastSize;
private Dimension minFrameSize;
private int tempX, tempY;
public ResizeUndecoratedJFrame() {
JFrame frame = new JFrame();
frame.setUndecorated(true);
JPanel p = new JPanel();
p.setMinimumSize(new Dimension(400, 300));
p.setPreferredSize(new Dimension(400, 300));
p.setMaximumSize(new Dimension(400, 300));
frame.add(p);
frame.setSize(400, 300);
minFrameSize = new Dimension(400, 300);
frame.setLocationRelativeTo(null);
frame.addMouseMotionListener(new MouseMotionAdapter() {
// change Cursor
@Override
public void mouseMoved(MouseEvent e) {
tempX = e.getX();
tempY = e.getY();
int w = frame.getWidth();
int h = frame.getHeight();
if ((tempX <= 3) || (tempY <= 3) || (w - tempX <= 3) || (h - tempY <= 3)) {
int type;
if (w - tempX <= 3) {
type = Cursor.E_RESIZE_CURSOR;
} else {
if (tempX <= 3) {
type = Cursor.W_RESIZE_CURSOR;
} else {
if (tempY <= 3) {
type = Cursor.N_RESIZE_CURSOR;
} else {
type = Cursor.S_RESIZE_CURSOR;
}
}
}
frame.setCursor(Cursor.getPredefinedCursor(type));
oldCursPosX = e.getX();
oldCursPosY = e.getY();
lastSize = frame.getSize();
} else {
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
@Override
public void mouseDragged(MouseEvent e) {
int type = frame.getCursor().getType();
if (type != Cursor.DEFAULT_CURSOR) {
// calculate the distance between last cursor position when it's pressed and the current position
int distX = 0, distY = 0;
int currentX = e.getX();
int currentY = e.getY();
boolean isWestOrNorth = false;
if (type == Cursor.E_RESIZE_CURSOR) {
distX = currentX - oldCursPosX;
} else {
if (type == Cursor.W_RESIZE_CURSOR) {
isWestOrNorth = true;
distX = oldCursPosX - currentX;
} else {
if (type == Cursor.N_RESIZE_CURSOR) {
isWestOrNorth = true;
distY = oldCursPosY - currentY;
} else {
distY = currentY - oldCursPosY;
}
}
}
int tempW = (int) (lastSize.getWidth() + distX);
int tempH = (int) (lastSize.getHeight() + distY);
// make sure user can't resize JFrame less than this minimum size
if ((distX < 0 && tempW <= minFrameSize.getWidth()) || (distY < 0 && tempH <= minFrameSize.getHeight())) {
return;
}
if (isWestOrNorth) {
frame.setLocation(Math.round(frame.getLocationOnScreen().x + e.getX() - tempX),
Math.round(frame.getLocationOnScreen().y + e.getY() - tempY));
}
frame.setSize(new Dimension(tempW, tempH));
}
}
});
frame.setVisible(true);
}
public static void main(String[] args) {
new ResizeUndecoratedJFrame();
}
}
答案1
得分: 1
我会使用MouseListener
来保存鼠标按下时的位置,而不是在mouseMoved
中执行此操作:
frame.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
oldCursPosX = e.getX();
oldCursPosY = e.getY();
}
});
在mouseDragged
中,类似这样的操作:
int x = frame.getX();
int y = frame.getY();
int width = frame.getWidth();
int height = frame.getHeight();
int dx = e.getX() - oldCursPosX;
int dy = e.getY() - oldCursPosY;
switch (type) {
case Cursor.N_RESIZE_CURSOR:
frame.setLocation(x, y+dy);
if (height-dy >= minFrameSize.height) {
frame.setSize(width, height-dy);
}
dy = 0; // frame has moved - it is the reference for coordinates
break;
case Cursor.S_RESIZE_CURSOR:
if (height+dy >= minFrameSize.height) {
frame.setSize(width, height+dy);
}
break;
// ... 类似于 W 和 E
}
oldCursPosX += dx;
oldCursPosY += dy;
设置光标仍然在mouseMoved()
中完成,只需删除赋值语句。
<sub>此答案中的代码不旨在完整、优化,甚至不是有效的 - 仅提供基本思路</sub>
英文:
I would use a MouseListener
to save the mouse position when pressed, instead of doing that inside mouseMoved
:
frame.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
oldCursPosX = e.getX();
oldCursPosY = e.getY();
}
});
and in mouseDragged
, something like:
int x = frame.getX();
int y = frame.getY();
int width = frame.getWidth();
int height = frame.getHeight();
int dx = e.getX() - oldCursPosX;
int dy = e.getY() - oldCursPosY;
switch (type) {
case Cursor.N_RESIZE_CURSOR:
frame.setLocation(x, y+dy);
if (height-dy >= minFrameSize.height) {
frame.setSize(width, height-dy);
}
dy = 0; // frame has moved - it is the reference for coordinates
break;
case Cursor.S_RESIZE_CURSOR:
if (height+dy >= minFrameSize.height) {
frame.setSize(width, height+dy);
}
break;
// ... similar for W and E
}
oldCursPosX += dx;
oldCursPosY += dy;
Setting the Cursor would still be done in mouseMoved()
, just remove the assignment statements.
<sub>code in this answer is not intended to be complete, optimized, not even valid - just the basic idea</sub>
答案2
得分: 0
有点奇怪的是,在拖动进行时移动窗口时发生了一些问题。尝试使用绝对坐标,并且如某人所说,在mousePressed
事件中保存位置。
我经常使用以下接口的实现来处理鼠标拖动事件:
public interface MouseDragger {
public void mouseDragged(int x, int y);
public void mouseReleased(int x, int y);
}
在被移动/调整大小的组件中,我会实现MouseListener
和MouseMotionListener
,并实现以下方法:
...
MouseDragger mouseDragger;
...
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
System.out.println(e);
mouseDragger = ResizeMouseDragger.get(this, e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (mouseDragger != null && e.getButton() == MouseEvent.BUTTON1) {
mouseDragger.mouseReleased(e.getX(), e.getY());
mouseDragger = null;
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (mouseDragger != null) {
System.out.println(e);
mouseDragger.mouseDragged(e.getX(), e.getY());
}
}
@Override
public void mouseMoved(MouseEvent e) {
Direction dir = Direction.hitTest(
getSize(), e.getX(), e.getY());
if (dir == null) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else {
setCursor(dir.getCursor());
}
}
ResizeMouseDragger
类如下:
class ResizeMouseDragger implements MouseDragger {
private final Component comp;
private final Direction dir;
private final Rectangle bounds;
private final int x;
private final int y;
public ResizeMouseDragger(Component comp, Direction dir, int x, int y) {
this.comp = comp;
this.bounds = comp.getBounds();
this.dir = dir;
Point pt = MouseInfo.getPointerInfo().getLocation();
this.x = pt.x;
this.y = pt.y;
}
public static MouseDragger get(Component comp, int x, int y) {
Direction dir = Direction.hitTest(comp.getSize(), x, y);
if (dir == null) {
return null;
} else {
return new ResizeMouseDragger(comp, dir, x, y);
}
}
@Override
public void mouseDragged(int x, int y) {
Point pt = MouseInfo.getPointerInfo().getLocation();
int dx = pt.x - this.x;
int dy = pt.y - this.y;
switch (dir) {
case NORTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y + dy,
bounds.width, bounds.height - dy);
}
break;
}
case SOUTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width, bounds.height + dy);
}
break;
}
case WEST: {
if (dx != 0) {
comp.setBounds(bounds.x + dx, bounds.y,
bounds.width - dx, bounds.height);
}
break;
}
case EAST: {
if (dx != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width + dx, bounds.height);
}
break;
}
}
}
@Override
public void mouseReleased(int x, int y) {
}
}
还有一个Direction
类:
public enum Direction {
NORTH(Cursor.N_RESIZE_CURSOR),
SOUTH(Cursor.S_RESIZE_CURSOR),
WEST(Cursor.W_RESIZE_CURSOR),
EAST(Cursor.E_RESIZE_CURSOR),
NORTH_WEST(Cursor.NW_RESIZE_CURSOR),
NORTH_EAST(Cursor.NE_RESIZE_CURSOR),
SOUTH_WEST(Cursor.SW_RESIZE_CURSOR),
SOUTH_EAST(Cursor.SE_RESIZE_CURSOR);
private static final int HANDLE_WIDTH = 4;
private final int cursor;
public static Direction hitTest(Dimension size, int x, int y) {
if (x < 0 || y < 0 || x > size.width || y > size.height) {
// outside of the frame
return null;
} else if (x <= HANDLE_WIDTH) {
// west
if (y <= HANDLE_WIDTH) {
return NORTH_WEST;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH_WEST;
} else {
return WEST;
}
} else if (x >= size.width-HANDLE_WIDTH) {
// east
if (y <= HANDLE_WIDTH) {
return NORTH_EAST;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH_EAST;
} else {
return EAST;
}
} else {
if (y <= HANDLE_WIDTH) {
return NORTH;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH;
} else {
// center
return null;
}
}
}
private Direction(int cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return Cursor.getPredefinedCursor(cursor);
}
}
英文:
There's something weird going on when you move a window while a drag is in progress. Try to use absolute coordinates, and, as someone has said, save the position on mousePressed event.
I often use an implementation of the following interface to handle mouse drag events:
public interface MouseDragger {
public void mouseDragged(int x, int y);
public void mouseReleased(int x, int y);
}
in the component being moved/resized, I would implement MouseListener and MouseMotionListener, and implement the following methods:
...
MouseDragger mouseDragger;
...
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
System.out.println(e);
mouseDragger = ResizeMouseDragger.get(this, e.getX(), e.getY());
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (mouseDragger != null && e.getButton() == MouseEvent.BUTTON1) {
mouseDragger.mouseReleased(e.getX(), e.getY());
mouseDragger = null;
}
}
@Override
public void mouseDragged(MouseEvent e) {
if (mouseDragger != null) {
System.out.println(e);
mouseDragger.mouseDragged(e.getX(), e.getY());
}
}
@Override
public void mouseMoved(MouseEvent e) {
Direction dir = Direction.hitTest(
getSize(), e.getX(), e.getY());
if (dir == null) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} else {
setCursor(dir.getCursor());
}
}
To class ResizeMouseDragger
looks like this:
class ResizeMouseDragger implements MouseDragger {
private final Component comp;
private final Direction dir;
private final Rectangle bounds;
private final int x;
private final int y;
public ResizeMouseDragger(Component comp, Direction dir, int x, int y) {
this.comp = comp;
this.bounds = comp.getBounds();
this.dir = dir;
Point pt = MouseInfo.getPointerInfo().getLocation();
this.x = pt.x;
this.y = pt.y;
}
public static MouseDragger get(Component comp, int x, int y) {
Direction dir = Direction.hitTest(comp.getSize(), x, y);
if (dir == null) {
return null;
} else {
return new ResizeMouseDragger(comp, dir, x, y);
}
}
@Override
public void mouseDragged(int x, int y) {
Point pt = MouseInfo.getPointerInfo().getLocation();
int dx = pt.x - this.x;
int dy = pt.y - this.y;
switch (dir) {
case NORTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y + dy,
bounds.width, bounds.height - dy);
}
break;
}
case SOUTH: {
if (dy != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width, bounds.height + dy);
}
break;
}
case WEST: {
if (dx != 0) {
comp.setBounds(bounds.x + dx, bounds.y,
bounds.width - dx, bounds.height);
}
break;
}
case EAST: {
if (dx != 0) {
comp.setBounds(bounds.x, bounds.y,
bounds.width + dx, bounds.height);
}
break;
}
}
}
@Override
public void mouseReleased(int x, int y) {
}
}
And I would have a Direction
class:
public enum Direction {
NORTH(Cursor.N_RESIZE_CURSOR),
SOUTH(Cursor.S_RESIZE_CURSOR),
WEST(Cursor.W_RESIZE_CURSOR),
EAST(Cursor.E_RESIZE_CURSOR),
NORTH_WEST(Cursor.NW_RESIZE_CURSOR),
NORTH_EAST(Cursor.NE_RESIZE_CURSOR),
SOUTH_WEST(Cursor.SW_RESIZE_CURSOR),
SOUTH_EAST(Cursor.SE_RESIZE_CURSOR);
private static final int HANDLE_WIDTH = 4;
private final int cursor;
public static Direction hitTest(Dimension size, int x, int y) {
if (x < 0 || y < 0 || x > size.width || y > size.height) {
// outside of the frame
return null;
} else if (x <= HANDLE_WIDTH) {
// west
if (y <= HANDLE_WIDTH) {
return NORTH_WEST;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH_WEST;
} else {
return WEST;
}
} else if (x >= size.width-HANDLE_WIDTH) {
// east
if (y <= HANDLE_WIDTH) {
return NORTH_EAST;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH_EAST;
} else {
return EAST;
}
} else {
if (y <= HANDLE_WIDTH) {
return NORTH;
} else if (y >= size.height-HANDLE_WIDTH) {
return SOUTH;
} else {
// center
return null;
}
}
}
private Direction(int cursor) {
this.cursor = cursor;
}
public Cursor getCursor() {
return Cursor.getPredefinedCursor(cursor);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论