我发现当一个模态JDialog启动第二个模态JDialog时,当第二个JDialog被释放时,第一个JDialog似乎(大部分)忽略了键盘。
我已经提供了一个示例程序来演示该问题。在运行代码时,我应该可以点击空格键(主JFrame中的按钮具有焦点)并启动第一个JDialog,其中包含一个按钮(也有焦点)。
我点击了空格键,第二个JDialog启动了。点击进入,第二个JDialog处理。
点击第一个JDialog上的空格键会导致无响应。 Alt-F4将关闭第一个JDialog,因此键盘未完全断开。
仅使用鼠标重复上述步骤,不会发生此问题。
所有这一切的背景是我想在对话框中设置默认按钮(用户在其中输入一些文本和其他数据)。如果我在第二个JDialog中注释掉setDefaultButton并且现在使用TAB移动,则不会发生此问题。
简而言之,我希望能够在JDialog上设置默认按钮(因此我可以点击回车键),但同时,我希望默认关注JTextField。
我使用OpenJDK(64位)在Ubuntu 13.10上。我发现无论使用GTK +外观还是金属外观(即没有设置任何外观和感觉)都会发生这种情况。
我无法在Windows XP上重现(使用Oracle Java 32位)。
在阅读一些帖子时,似乎Linux和Java有一些焦点问题,因此我不确定这是否是我的编程错误,或者我偶然发现了Linux / Java问题。
有什么想法吗?
下面是重现问题的示例代码。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Test extends JFrame
{
public Test()
{
JButton button = new JButton( "Test" );
button.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent actionEvent ) { new Test1( Test.this ); } } );
JPanel panel = new JPanel();
panel.add( button );
getContentPane().add( panel );
pack();
setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
setVisible( true );
}
protected class Test1 extends JDialog
{
public Test1( JFrame owner )
{
super( owner );
JButton button = new JButton( "1" );
button.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent actionEvent ) { new Test2( Test1.this ); } } );
JPanel panel = new JPanel();
panel.add( button );
getContentPane().add( panel );
pack();
setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
setLocationRelativeTo( null );
setModalityType( ModalityType.APPLICATION_MODAL );
setVisible( true );
}
}
protected class Test2 extends JDialog
{
public Test2( JDialog owner )
{
super( owner );
JTextField textField = new JTextField();
JButton button = new JButton( "2" );
getRootPane().setDefaultButton( button );
button.addActionListener
(
new ActionListener()
{
public void actionPerformed( ActionEvent actionEvent )
{
// Test2.this.getRootPane().setDefaultButton( null ); // Makes no difference!
Test2.this.dispose();
}
}
);
JPanel panel = new JPanel( new BorderLayout() );
panel.add( textField, BorderLayout.CENTER );
panel.add( button, BorderLayout.SOUTH );
getContentPane().add( panel );
pack();
setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
setLocationRelativeTo( null );
setModalityType( ModalityType.APPLICATION_MODAL );
setVisible( true );
}
}
public static void main( String[] args )
{
new Test();
}
}