Java 当JFormattedTextField获得焦点时,如何选择其中的所有文本?
我有一个使用Swing的小型Java桌面应用程序。有一个数据输入对话框,其中包含一些不同类型的输入字段(JTextField、JComboBox、JSpinner、JFormattedTextField)。当我通过在表单中使用Tab键或鼠标单击来激活JFormattedTextFields时,我希望它选择当前包含的所有文本。这样,用户就可以开始键入并覆盖默认值 我该怎么做?我确实使用了一个FocusListener/FocusAdapter,它在JFormattedTextField上调用selectAll(),但它没有选择任何内容,尽管调用了FocusAdapter的FocusGaund()方法(请参见下面的代码示例)Java 当JFormattedTextField获得焦点时,如何选择其中的所有文本?,java,user-interface,swing,Java,User Interface,Swing,我有一个使用Swing的小型Java桌面应用程序。有一个数据输入对话框,其中包含一些不同类型的输入字段(JTextField、JComboBox、JSpinner、JFormattedTextField)。当我通过在表单中使用Tab键或鼠标单击来激活JFormattedTextFields时,我希望它选择当前包含的所有文本。这样,用户就可以开始键入并覆盖默认值 我该怎么做?我确实使用了一个FocusListener/FocusAdapter,它在JFormattedTextField上调用sel
有什么想法吗?有趣的是,选择所有文本显然是JTextField和JSpinner的默认行为,至少在切换表单时是这样。使用SwingUtilities.invokeLater包装调用,以便在处理所有挂起的AWT事件后发生:
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
pricePerLiter.selectAll();
}
});
}
});
这是因为JFormattedTextfield覆盖processFocusEvent,以便在获得焦点/丢失焦点时格式化 一种可靠的方法是扩展JFormattedTextField并重写processFocusEvent方法:
new JFormattedTextField("...") {
protected void processFocusEvent(FocusEvent e) {
super.processFocusEvent(e);
if (e.isTemporary())
return;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
selectAll();
}
});
}
};
使用focusListener可能并不总是有效。因为这取决于相对于processFocusEvent调用focusListener的时间。除上述内容外,如果您希望所有文本字段都使用focusListener,可以执行以下操作:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});
camickr的代码可以稍微改进。当焦点从JTextField传递到另一种组件(如按钮)时,最后一个自动选择不会被清除。可以通过以下方式进行修复:
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener()
{
@Override
public void propertyChange(final PropertyChangeEvent e)
{
if (e.getOldValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JTextField oldTextField = (JTextField)e.getOldValue();
oldTextField.setSelectionStart(0);
oldTextField.setSelectionEnd(0);
}
});
}
if (e.getNewValue() instanceof JTextField)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
JTextField textField = (JTextField)e.getNewValue();
textField.selectAll();
}
});
}
}
});
我知道这有点过时,但我提出了一个更干净的解决方案,没有调用器:
private class SelectAllOfFocus extends FocusAdapter {
@Override
public void focusGained(FocusEvent e) {
if (! e.isTemporary()) {
JFormattedTextField textField = (JFormattedTextField)e.getComponent();
// This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
// do anything. Otherwise, it calls setValue, and the selection is lost.
textField.setText(textField.getText());
textField.selectAll();
}
}
}
谢谢,就这样。我只能猜测NumberFormatter正在做一些撤销selectAll()的事情?+1需要这个,我自己也记不起怎么做了,谷歌搜索并立即找到了答案。谢谢当您已经在EDT线程上时,为什么要使用invokeLater执行它?因为
invokeLater
确保所有挂起的AWT事件都已处理。我不喜欢此代码,因为它修改组件内部状态,只是为了获得选择?
private class SelectAllOfFocus extends FocusAdapter {
@Override
public void focusGained(FocusEvent e) {
if (! e.isTemporary()) {
JFormattedTextField textField = (JFormattedTextField)e.getComponent();
// This is needed to put the text field in edited mode, so that its processFocusEvent doesn't
// do anything. Otherwise, it calls setValue, and the selection is lost.
textField.setText(textField.getText());
textField.selectAll();
}
}
}