default按钮不会导致jformattedtextfield提交当前编辑

nhaq1z21  于 2021-07-11  发布在  Java
关注(0)|答案(1)|浏览(277)

我在想,我所期望的 JFormattedTextField 与默认按钮结合使用是正确的。在编辑 JFormattedTextField ,通常要提交值然后使用它,这通常发生在 focusLost 或者有时候 ActionListener 手动触发。现在,如果这样的文本字段在 JDialog 它有一个 DefaultButton 已定义,使用ctrl+enter触发默认按钮不会导致当前焦点 JFormattedTextField 触发它是 focusLost 事件。
现在,我看到两种解决方案:
手动确保所有inut字段处于comitt(或还原)状态
使用 SwingUtilities.InvokeLaterActionListener 默认按钮的
然而,这两个看起来都很脏,尤其是第一个,因为要扩展所说的对话框而不忘记处理组件是不太容易的。第二种是不受欢迎的,因为 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 );
  }
}
z18hc3ub

z18hc3ub1#

是的,当 JFormattedTextField 有输入焦点,你激活 defaultButton ,的 JFormattedTextField 不会失去焦点,因此不会提交值。
请参阅如何使用格式化文本字段。
这里有一句话:
格式化文本字段的文本及其值是两个不同的属性,并且值通常滞后于文本。
文本属性由 JTextField 班级。此属性始终反映字段显示的内容。值属性,由 JFormattedTextField 类,可能不会反映字段中显示的最新文本。用户键入时,text属性会更改,但value属性在提交更改之前不会更改。
我看到了两种可能的解决方案(尽管我认为还有更多)。
actionPerformed() 方法,或者调用 getText() 而不是 getValue() ,或呼叫 commitEdit() 打电话之前 getValue() ,即。

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() 打电话。

相关问题