为什么我的 java gui 第一次移动时会“跳跃”?

问题描述 投票:0回答:2

我有一个简单的java gui(下面的代码),由于某种原因,当我第一次尝试移动或调整它的大小时,它会“跳”回原来的位置。所以基本上我必须移动 GUI 两次才能让它移动一次,因为一旦我第一次释放鼠标,它就会弹回到原来出现的位置。

import javax.swing.*;

public class JFrameTester {

  public static void main(String[] args) {

    JFrame f = new JFrame("A JFrame");
    f.setSize(250, 250);
    f.setLocation(300,200);
    f.getContentPane().add(new JTextArea(10, 40));    
    //f.pack();    
    f.setVisible(true);
    //f.validate();
  }

}

我在 GNU Linux 上运行 java 1.6。我正在将显示导出回我的 Windows 计算机,想知道它是否与 X11 转发有关,因为当我在 Windows 中运行 gui 时,它没有显示此行为。但是,当我在 Fedora Linux 机器(带有 java 1.7)上运行此 gui 时,它根本不显示此行为 - 无论是否导出显示。

java linux swing user-interface x11
2个回答
4
投票

几个明显的问题:

以下示例结合了这些建议:

import java.awt.EventQueue; import javax.swing.*; public class JFrameTester { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { JFrame f = new JFrame("A JFrame"); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JScrollPane(new JTextArea(10, 40))); f.pack(); f.setLocationByPlatform(true); f.setVisible(true); } }); } }
    

0
投票
在 Cygwin X11 下使用 AWT 或 Swing 应用程序时会出现此问题 服务器。仅当您致电

setLocation

setLocationRelativeTo
 在构造窗口对象时。 (但是如果
你不调用
setLocation
,那么窗口就会出现在左上角
拐角处,不方便。)

具体症状是:当第一次显示窗口或对话框时,并且 用户尝试通过拖动标题栏来移动它,拖动后 完成后,窗口跳回到原来的位置。在那之后, 移动窗口工作正常。

我找到的解决方案是以编程方式调整窗口的位置 首次显示后不久:

// Call this *before* 'setVisible(true)'. f.addWindowListener(new java.awt.event.WindowAdapter() { @Override public void windowOpened(java.awt.event.WindowEvent e) { final java.awt.Window w = e.getWindow(); javax.swing.Timer t = new javax.swing.Timer(100 /*ms*/, new java.awt.event.ActionListener() { @Override public void actionPerformed(java.awt.event.ActionEvent e) { // Slightly adjust the window position to work around a // bug where the window manager "rejects" the first // attempt to move the window. int y = w.getLocation().y; w.setLocation(w.getLocation().x, y+1); } }); t.setRepeats(false); t.start(); } });
如上所述,这必须在 

setVisible(true)

 之前调用,否则你
可能会错过
windowOpened
活动。使用时这一点也很重要
a 
JDialog
 因为在这种情况下,
setVisible(true)
 会阻塞,直到
对话框已关闭。

选择移动 1 个像素是为了最大限度地减少干扰,因为调整 通常对用户可见。我说通常是因为有时(也许 四分之一)调整不会发生,即使 成功解除了潜在的错误。移动 0 像素不会 解除错误。

不幸的是,计时器对于避免失去竞争条件是必要的 与窗口管理器。在我的测试中,没有计时器,窗口 当 用户首先移动它。使用 100 毫秒计时器时,我从未观察到它失败 (经过超过 100 次测试),但 50 毫秒还不够。这将取决于 当然是机器速度。

版本:Linux 上的 Java 1.8.0_92 和 Windows 10 上的 cygwin 3.4.7。

© www.soinside.com 2019 - 2024. All rights reserved.