默认按钮不会导致 JFormattedTextField 提交当前编辑
Default Button doesn't cause JFormattedTextField to commit current edit
我想知道我期望 JFormattedTextField
与默认按钮结合使用的方式是否正确。在编辑 JFormattedTextField
的值时,您通常希望提交该值然后使用它,这通常发生在 focusLost
或有时手动触发 ActionListener
时。现在,如果这样的文本字段位于定义了 DefaultButton
的 JDialog
中,则使用 Ctrl+Enter 触发默认按钮不会导致当前聚焦的 JFormattedTextField
触发它的 focusLost
事件。
现在,我看到两个解决方案:
- 手动确保所有 inupt 字段都处于提交(或还原)状态
- 在默认按钮
ActionListener
中使用一个SwingUtilities.InvokeLater
但是,这两个看起来都很脏,尤其是第一个,因为在不忘记处理组件的情况下扩展所述对话框并不是很容易。第二个在我看来是相当不受欢迎的,因为更多的 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
不会失去焦点,因此不会提交该值。
参考How to Use Formatted Text Fields.
这是一个引用:
A formatted text field's text and its value are two different properties, and the value often lags behind the text.
The text property is defined by the JTextField
class. This property always reflects what the field displays. The value property, defined by the JFormattedTextField
class, might not reflect the latest text displayed in the field. While the user is typing, the text property changes, but the value property does not change until the changes are committed.
我看到了两种可能的解决方案(尽管我想还有更多)。
在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()
调用中。
我想知道我期望 JFormattedTextField
与默认按钮结合使用的方式是否正确。在编辑 JFormattedTextField
的值时,您通常希望提交该值然后使用它,这通常发生在 focusLost
或有时手动触发 ActionListener
时。现在,如果这样的文本字段位于定义了 DefaultButton
的 JDialog
中,则使用 Ctrl+Enter 触发默认按钮不会导致当前聚焦的 JFormattedTextField
触发它的 focusLost
事件。
现在,我看到两个解决方案:
- 手动确保所有 inupt 字段都处于提交(或还原)状态
- 在默认按钮
ActionListener
中使用一个SwingUtilities.InvokeLater
但是,这两个看起来都很脏,尤其是第一个,因为在不忘记处理组件的情况下扩展所述对话框并不是很容易。第二个在我看来是相当不受欢迎的,因为更多的 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
不会失去焦点,因此不会提交该值。
参考How to Use Formatted Text Fields.
这是一个引用:
A formatted text field's text and its value are two different properties, and the value often lags behind the text.
The text property is defined by theJTextField
class. This property always reflects what the field displays. The value property, defined by theJFormattedTextField
class, might not reflect the latest text displayed in the field. While the user is typing, the text property changes, but the value property does not change until the changes are committed.
我看到了两种可能的解决方案(尽管我想还有更多)。
在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()
调用中。