我有一个应用程序,如果用户操作需要一定的时间,则会显示一个对话框,界面正在处理该操作。通常在操作完成后,对话框关闭,用户可以继续执行之前正在执行的操作。这似乎几乎总是有效,但是时不时地将焦点从聚焦的组件转移到焦点链中它后面2个位置的组件。
我无法创建一个小的示例程序来显示究竟发生了什么,但我已经能够将问题调试到我希望有人可以帮助我的地方。
似乎发生了这样的事情:
对于4 *:在它工作的情况下似乎不同的东西和它不存在的情况是WComponentPeer在parentWindow的焦点请求之后检查,在正确的情况下,parentWindow.isFocused()是如果为true,则在失败的情况下,parentWindow.isFocused()将返回false。打开焦点记录时显示的日志记录是“rejectFocusRequestHelper [...]等待请求的异步处理”。
这似乎表明WComponentPeer知道必须异步处理焦点请求的可能性,但DKFM却不知道。
相关的堆栈跟踪如下:
KeyboardFocusManager.setMostRecentFocusOwner(Window, Component) line: 1814
KeyboardFocusManager.setMostRecentFocusOwner(Component) line: 1801
TheComponent(Component).requestFocusHelper(boolean, boolean, CausedFocusEvent$Cause) line: 7618 (3)
TheComponent(Component).requestFocusInWindow(CausedFocusEvent$Cause) line: 7533
DefaultKeyboardFocusManager.doRestoreFocus(Component, Component, boolean) line: 172 (6)
DefaultKeyboardFocusManager.restoreFocus(Window, Component, boolean) line: 151 (2)
DefaultKeyboardFocusManager.restoreFocus(WindowEvent) line: 134
DefaultKeyboardFocusManager.dispatchEvent(AWTEvent) line: 302
ProgressDialog(Component).dispatchEventImpl(AWTEvent) line: 4731 (1)
所以我的问题是,我在这里查看Java错误吗?
此外,文档提到您不应该假设更改焦点是同步完成的,但它不能解释何时它是同步的,何时不是因为触发焦点系统在Java中异步处理某些焦点请求而其他同步处理?
编辑:它也可能是一个事件订购的东西。 在正确的情况下查看KeyboardFocusManager中的focusedWindow时,它是这样的:
在失败的情况下,就像这样:
似乎在实际显示对话框之前将其删除。将主框架清除为活动窗口的事件在两种情况下都是WINDOW_FOCUS_LOST TimedWindowEvent,对话框为对面。
答案 0 :(得分:0)
从我现在可以看出它是由Java bug引起的。因为我注意到对话框从未成为焦点,所以我能够在一个小型Java应用程序中重现它:
public class TestFocusStuff extends JFrame implements ActionListener
{
private final MyDialog mDialog = new MyDialog();
public static void main(String[] args)
{
TestFocusStuff tfs = new TestFocusStuff();
tfs.setVisible(true);
}
public TestFocusStuff()
{
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
Container c = getContentPane();
c.setLayout(new FlowLayout());
for (int i = 0; i < 10; i++)
{
JTextField tf = new JTextField(10);
c.add(tf);
tf.addActionListener(this);
}
pack();
}
@Override
public void actionPerformed(ActionEvent e)
{
mDialog.showQuickly();
}
private static class MyDialog extends JDialog
{
public void showQuickly()
{
setVisible(true);
setVisible(false);
}
}
}
在任何文本字段中按Enter将弹出对话框并立即将其关闭。焦点会改变,就好像Tab被按两次一样。
如果我添加一个focuslistener并且在收到该事件后只关闭对话框,我希望这个应该修复。
编辑:我现在可以确认在关闭对话框之前等待WindowFocusEvent.windowGainedFocus确实有助于防止错误。