似乎Ubuntu有一个错误(也许只有unity)。JFrame的装饰被考虑在getLocation()
和getSize()
,但不考虑setLocation()
和setSize()
。这会导致奇怪的行为。例如,如果您在显示框架并更改尺寸后使用 pack(),则框架将下降 20 像素......
为了说明一个具体案例,当它变得非常烦人时,我做了一个SSCCE。这是一个带有基本JPanel的JFrame。如果拖动面板,JFrame 应该会移动。
在Windows下,它按预期工作。在 Ubuntu 下,如果我这样做setUndecorated(true)
它也可以正常工作,但如果我让装饰,JFrame 就会变得疯狂!
public class Test {
private static JFrame mainFrame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame = new JFrame("test");
mainFrame.setSize(300,20);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
Container pane = mainFrame.getContentPane();
pane.addMouseMotionListener(new MouseMotionListener() {
private int posX = 0, posY = 0;
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getX() - posX + mainFrame.getX();
int y = e.getY() - posY + mainFrame.getY();
mainFrame.setLocation(x, y);
}
@Override
public void mouseMoved(MouseEvent e) {
posX = e.getX();
posY = e.getY();
}
});
}
});
}
}
我不知道我该如何解决这个问题。如何获得窗户装饰的尺寸?而且我不知道与哪个版本的 Ubuntu 有关。如果这只是一个 Unity 问题,我什至不知道如何确定我的用户是否正在使用 Unity......
有什么解决方法的想法吗?
编辑 :好的,MadProgrammer确实提供了更好的代码,但有时仍然会出现错误。我相应地编辑了我的鼠标侦听器以跟踪错误:
pane.addMouseMotionListener(new MouseMotionListener() {
private int posX = 0, posY = 0;
@Override
public void mouseDragged(MouseEvent e) {
int x = e.getXOnScreen() - posX;
int y = e.getYOnScreen() - posY;
mainFrame.setLocation(x, y);
System.out.println("drag : border ignored / border considered : "+(mainFrame.getY()+e.getY())+" / "+e.getYOnScreen());
}
@Override
public void mouseMoved(MouseEvent e) {
posX = e.getXOnScreen() - mainFrame.getX();
posY = e.getYOnScreen() - mainFrame.getY();
System.out.println("move : border ignored / border considered : "+e.getY()+" / "+posY);
}
});
每次 2 个值相同时,都意味着该错误将在下次单击时发生。否则,值会有所不同。在其他操作系统上,值始终相同。实际上,它们应该总是或相同,或者总是不同的。我不明白他们怎么会有时相等,有时不同......
Ubuntu 可以测试,但我在 MacOS 和 Windows 上使用过类似的东西
import java.awt.Container;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
private static JFrame mainFrame;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame = new JFrame("test");
mainFrame.setSize(300, 100);
mainFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mainFrame.setVisible(true);
Container pane = mainFrame.getContentPane();
MouseAdapter ma = new MouseAdapter() {
private Point offset;
@Override
public void mouseDragged(MouseEvent e) {
if (offset != null) {
Point pos = e.getLocationOnScreen();
int x = pos.x - offset.x;
int y = pos.y - offset.y;
System.out.println(x + "x" + y);
SwingUtilities.getWindowAncestor(e.getComponent()).setLocation(x, y);
}
}
@Override
public void mousePressed(MouseEvent e) {
Point pos = SwingUtilities.getWindowAncestor(e.getComponent()).getLocation();
// Point pos = e.getComponent().getLocationOnScreen();
offset = new Point(e.getLocationOnScreen());
System.out.println(pos + "/" + offset);
offset.x -= pos.x;
offset.y -= pos.y;
System.out.println(offset);
}
};
pane.addMouseListener(ma);
pane.addMouseMotionListener(ma);
}
});
}
}
这应该适用于装饰和未装饰的窗口,因为它需要组件的位置(在屏幕上)和窗口当前位置之间的差异。 拖动时,它会计算与单击点的移动距离,并相应地更新窗口的位置(允许单击的原始偏移)