JFrame 位置错误 Ubuntu(Unity?)
JFrame wrong location with Ubuntu (Unity ?)
好像Ubuntu有bug(可能只有unity)。 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();
}
});
}
});
}
}
我不知道该如何解决。如何获得 windows 装饰的大小?而且我不知道 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);
}
});
每次2个值相同,就说明下次点击会出现bug。否则,值不同。在其他 OS 上,值始终相同。实际上,它们应该是或者总是相同的,或者总是不同的。我不明白他们为什么有时相等有时不同...
我没有 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);
}
});
}
}
这应该适用于装饰和未装饰的 windows,因为它需要组件(在屏幕上)的位置与 windows 当前位置之间的差异。拖动时,它会计算距点击点的移动距离并相应地更新 window 的位置(考虑到点击的原始偏移量)
好像Ubuntu有bug(可能只有unity)。 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();
}
});
}
});
}
}
我不知道该如何解决。如何获得 windows 装饰的大小?而且我不知道 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);
}
});
每次2个值相同,就说明下次点击会出现bug。否则,值不同。在其他 OS 上,值始终相同。实际上,它们应该是或者总是相同的,或者总是不同的。我不明白他们为什么有时相等有时不同...
我没有 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);
}
});
}
}
这应该适用于装饰和未装饰的 windows,因为它需要组件(在屏幕上)的位置与 windows 当前位置之间的差异。拖动时,它会计算距点击点的移动距离并相应地更新 window 的位置(考虑到点击的原始偏移量)