我正在尝试做一些训练项目,在这个项目中,我添加了一个未修饰的 JFrame,因此我向其中添加了 MouseMotionListener 以更改鼠标光标,然后更改其大小和位置,使其看起来像任何可调整大小的修饰 JFrame
pblm:在北面和西面,框架没有调整大小,它保持改变位置而不改变它的大小,但是当我在调试模式下运行程序时它工作
我尝试使用线程和 setBounds 而不是 setSize,我也尝试添加 frame.revalidate() 和 frame.repaint(),但没有任何效果,任何建议
谢谢你的时间
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();
}
}
我会在按下时使用
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;
// ... similar for W and E
}
oldCursPosX += dx;
oldCursPosY += dy;
设置 Cursor 仍然会在
mouseMoved()
中完成,只需删除赋值语句即可。
这个答案中的代码是not旨在完成,优化,甚至无效 - 只是基本的想法
在拖动过程中移动窗口时会发生一些奇怪的事情。尝试使用绝对坐标,并且正如有人所说,将位置保存在 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
看起来像这样:
类 ResizeMouseDragger 实现 MouseDragger { 私人最终组件补偿; 私人最终方向目录; 私有最终矩形边界; 私人最终诠释 x; 私人最终诠释 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);
}
}