我有一个使用Swing的小型Java桌面应用程序。有一个数据输入对话框,其中包含一些不同类型的输入字段(JTextField,JComboBox,JSpinner,JFormattedTextField)。当我通过在表单中进行选项卡或通过鼠标单击来激活JFormattedTextField时,我希望它选择它当前包含的所有文本。这样,用户就可以开始输入并覆盖默认值。
我该怎么做?我确实使用了一个在JFormattedTextField上调用selectAll()的FocusListener / FocusAdapter,但它没有选择任何东西,尽管调用了FocusAdapter的focusGained()方法(参见下面的代码示例)。
private javax.swing.JFormattedTextField pricePerLiter;
// ...
pricePerLiter.setFormatterFactory(
new JFormattedTextField.AbstractFormatterFactory() {
private NumberFormatter formatter = null;
public JFormattedTextField.AbstractFormatter
getFormatter(JFormattedTextField jft) {
if (formatter == null) {
formatter = new NumberFormatter(new DecimalFormat("#0.000"));
formatter.setValueClass(Double.class);
}
return formatter;
}
});
// ...
pricePerLiter.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusGained(java.awt.event.FocusEvent evt) {
pricePerLiter.selectAll();
}
});
有什么想法吗?有趣的是,选择它的所有文本显然是JTextField和JSpinner的默认行为,至少在表格中是否有标签。
答案 0 :(得分:66)
使用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();
}
});
}
});
答案 1 :(得分:14)
除了上述内容之外,如果您想要所有文本字段,您可以这样做:
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();
}
});
}
}
});
答案 2 :(得分:7)
我知道这有点陈旧,但我提出了一个更清洁的解决方案,没有invokeLater:
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();
}
}
}
答案 3 :(得分:6)
这是因为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调用它的时间。
答案 4 :(得分:2)
可以略微改进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();
}
});
}
}
});