【发布时间】:2015-06-15 01:19:11
【问题描述】:
似乎 Ubuntu 有一个错误(可能只是统一)。 getLocation() 和 getSize() 考虑了 JFrame 的装饰,但 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 确实提供了更好的代码,但有时仍会出现该错误。我相应地编辑了我的 MouseListener 以跟踪错误:
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);
}
});
每次两个值相同时,意味着下次点击时会出现该错误。否则,值不同。在其他操作系统上,这些值始终相同。实际上,它们应该总是或相同,或总是不同。我不明白它们为什么有时相同有时不同......
【问题讨论】:
-
鼠标事件与生成它们的容器相关,这意味着位置 0x0 实际上是容器的左上角。由于您已经在
contentPane上注册了MouseListener,因此您的鼠标坐标在它的上下文中。也许可以尝试将MouseEvent坐标转换为屏幕坐标,这样会更兼容框架的坐标 -
嗯...我尝试了getLocationOnScreen和getLocation的各种组合,但我没有成功获得预期的行为...看起来在移动之后,getLocation方法将返回正确的值,但经过一些毫秒后,它会考虑边框...
-
我可能不会在
mouseMoved事件上更新posX和posY,就个人而言,我会使用mouseClicked设置锚点,然后计算与此的距离你已经拖动了(考虑到点击点和框架的原始位置之间的差异) -
这是另一种可能性,但我相信它不会改变任何事情。如果我的方法是错误的,它不会与 setUndecorated(true) 一起使用。它只会使代码更复杂,因为我需要同时监听 Mouse 事件和 MouseMotion 事件。但我认为您对 getYOnScreen() 的看法是正确的。如果不考虑边界,我应该能够找到返回 0 的计算,否则返回边界的高度。
标签: java swing ubuntu jframe location