gpt4 book ai didi

java - 模态 JDialog 的 1x1 维度

转载 作者:搜寻专家 更新时间:2023-11-01 02:13:58 26 4
gpt4 key购买 nike

问题

我们的独立 Swing 应用程序在某些特定事件(按钮单击等)中显示模态 JDialog该对话框包含一些其他 Swing 组件(JLabels、JButtons 等)。我们调用JDialog.pack()(或JOptionPaneshowDialog(...) 方法隐式调用它)。通过 pack() 方法计算的尺寸总是恒定的(例如 300x100 像素。)不幸的是,有时可见对话框的真实尺寸是 1x1 像素(JDialog.getSize( ).equals(新维度(1, 1))).

JDialog初始化

我们在应用程序中初始化 JDialog 有两种方法。我们检查了两种初始化方法总是从 EventDispatchThread 调用。

第一种方法

我们只是创建了一个 ADialog 的实例,它是 JDialog 的子类。这是我们初始化过程的一个片段:

ADialog dialog = new ADialog();
dialog.setContentPane(content);
dialog.setVisible(true);

这是我们的 ADialog 实现:

public class ADialog extends JDialog implements ComponentListener {

public JfosDialog(Frame owner) {
super(owner);
init();
}

private void init() {
super.addComponentListener(this);
}

@Override
public void componentShown(ComponentEvent e) {
// Calling pack() at this place is really weird, but we
// have to do it since some subclasses put their
// content to dialog in overriden componentShown().
pack();
}

@Override
public void componentMoved(ComponentEvent e) { /** not interested */ }

@Override
public void componentResized(ComponentEvent e) { /** not interested */ }
}

第二种方法

public JOptionPane showDialog(...) {
JOptionPane jop = new JOptionPane(message, msgType, option, null, textMessages);
JDialog dialog = jop.createDialog(owner, titleMsg);
setDialogTraversal(dialog);
dialog.setVisible(true);
dialog.dispose();
return jop;
}

可重复性

环境

  • Ubuntu 12.04., JRE 1.6/JRE 1.7/OpenJDK 1.6
  • Windows XP,JRE 1.6.u16

用第一种初始化方法重现问题

我们只是显示然后隐藏对话 N 次(0 < N < 1000),并且一次对话的维度是 1x1(线程问题、竞争条件的迹象)。由于这个问题的性质是非常随机的,我们写的很简单 java.awt.Robot循环显示和隐藏对话框的脚本。它只是比手动操作更舒服。

使用第二种初始化方法重现问题

步骤同第一种方法:只显示然后隐藏对话框N次。不幸的是,我们无法在我们的开发环境中重现它,但它可以很容易地在生产 PC 中重现(CPU 与我们的开发环境不同,安装了一些永久创建系统负载的防病毒软件等)

到目前为止,我们无法在某种测试/示例项目中重现该问题。这可能表明我们的应用程序有问题。但是,问题似乎出在 Swing 的 native 代码中(请参阅“跟踪”部分)。

追踪

我们在 64 位 OpenJDK 1.6.0_24 中追踪了问题的原因。我们发现 JDialog 的维度被 XToolkit 触发的 XConfigureEvent 修改。该事件在本地方法调用返回后在 XToolkit.run(boolean) 方法的事件循环中构造。

为了简化事情,我在这里只发布了一个代码片段,说明了 XToolkit 的事件循环机制和我们的跟踪结果。您还可以看到 full source code here .

public class XToolkit ... {
...
public void run(boolean loop) {
XEvent ev = new XEvent();
while(true) {
awtLock();
try {
if (loop == SECONDARY_LOOP) {
...
} else {
...

// ===========================================
// The following invocation of native method sometimes
// updates ev object in a way that ev.get_type() method returns value 22
// indicating that the event's type is XConfigureEvent.
// In such case, as I mentioned in text above, the value of
// ev.get_xconfigure().get_width() / .get_height()
// is sometimes 1.

XlibWrapper.XNextEvent(getDisplay(),ev.pData); // <-----

// ===========================================
}
...
// The XConfigureEvent with get_width() == 1 and
// get_heigth() == 1 is dispatcher here:
dispatchEvent(ev); // <-----
...
} catch (...) {
...
}
}
}
...
}

您是否有任何想法如何修复此错误/更深入地跟踪它/更稳健地重现它...?

我很感激任何想法,因为这个错误真的很痛苦。

最佳答案

pack() 应遵循组件的首选(或最小尺寸,具体取决于布局管理器)。

尝试为对话框中的组件明确设置最小和首选大小,看看是否能解决问题。

就竞争条件而言,它也可能是代码中的不正确初始化。当布局管理器查询它们的首选(或最小尺寸)时,大多数组件将显示它们的内容(例如 JLabel 的文本)。因此,可能填充组件的代码并不总是以相同的顺序运行。您确定在 AWT 线程上创建了对话框和所有包含的组件吗?

关于java - 模态 JDialog 的 1x1 维度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10841829/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com