默认按钮不会导致 JFormattedTextField 提交当前编辑



我想知道JFormattedTextField与默认按钮结合使用的方式是否正确。编辑JFormattedTextField的值时,通常需要提交该值,然后使用它,这种情况通常发生在focusLost上,有时也发生在手动触发ActionListener时。现在,如果这样的文本字段位于定义了DefaultButtonJDialog内部,则用Ctrl+Enter触发默认按钮不会导致当前关注的JFormattedTextField触发其focusLost事件。

现在,我看到了两种解决方案:

  1. 手动确保所有inupt字段都处于委托(或还原(状态
  2. 在默认按钮的ActionListener中使用SwingUtilities.InvokeLater

然而,这两个似乎都很脏,尤其是第一个,因为在不忘记处理组件的情况下扩展所述对话框不是很容易。第二种是不可取的imo,因为更多的invokeLater通常意味着更多的代码更难调试。

有更好的方法解决这个问题吗?

示例:

import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class DefaultButton
{
public static void main( String[] args )
{
JFrame frame = new JFrame();
JFormattedTextField field = new JFormattedTextField();
field.setValue( "HELLO" );
JButton defaultButton = new JButton( "Default" );
defaultButton.addActionListener( __ ->
{
JOptionPane.showMessageDialog( frame, "You've chosen: " + field.getValue() );
} );
frame.getRootPane().setDefaultButton( defaultButton );
JPanel panel = new JPanel( new BorderLayout() );
panel.add( field, BorderLayout.NORTH );
panel.add( defaultButton, BorderLayout.SOUTH );
frame.add( panel );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}

是,当JFormattedTextField具有输入焦点并且您激活defaultButton时,JFormattedTextField不会失去焦点,因此不会提交该值。

请参阅如何使用格式化的文本字段
这里有一个报价:

格式化文本字段的文本及其值是两个不同的属性,并且该值通常滞后于文本
text属性由JTextField类定义。此属性始终反映字段显示的内容。JFormattedTextField类定义的属性可能无法反映字段中显示的最新文本。当用户键入时,text属性会更改,但value属性不会更改,直到提交更改

我看到了两种可能的解决方案(尽管我认为还有更多(
actionPerformed()方法中,调用getText()而不是getValue(),或者在调用getValue()之前调用commitEdit(),即

JOptionPane.showMessageDialog( frame, "You've chosen: " + field.getText() );

try {
field.commitEdit();
}
catch (java.text.ParseException x) {
x.printStackTrace();
}
JOptionPane.showMessageDialog(frame, "You've chosen: " + field.getValue());

编辑

我相信这就是你想要的。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.KeyboardFocusManager;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class DefaultButton
{
public static void main( String[] args )
{
JFrame frame = new JFrame();
JFormattedTextField field = new JFormattedTextField();
field.setValue( "HELLO" );
JButton defaultButton = new JButton( "Default" );
defaultButton.addActionListener( __ ->
{
KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
if (kfm.getFocusOwner() == field) {
kfm.focusNextComponent();            
}
EventQueue.invokeLater(() -> JOptionPane.showMessageDialog( frame, "You've chosen: " + field.getValue() ));
} );
frame.getRootPane().setDefaultButton( defaultButton );
JPanel panel = new JPanel( new BorderLayout() );
panel.add( field, BorderLayout.NORTH );
panel.add( defaultButton, BorderLayout.SOUTH );
frame.add( panel );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
frame.setVisible( true );
}
}

专注于方法actionPerformed()。如果JFormattedTextField当前具有焦点,则强制焦点移动到下一个组件。无论哪个组件具有键盘焦点,都要将JOptionPane的显示封装在invokeLater()调用中。

相关内容

  • 没有找到相关文章

最新更新