Заставьте JSpinner Выделять Текст При Фокусировке
Я хотел бы изменить поведение JSpinner так, чтобы при нажатии на текст он выделял его. Это облегчает замену поля на нужное значение. К сожалению, я не могу заставить поведение работать, и вместо этого он просто вставляет курсор в текст, не выбирая то, что уже есть.
Я попытался добавить слушателя фокуса как к самому JSpinner, так и к текстовой области, через ((DefaultEditor) this.getEditor()).getTextField()
, но ни один из них, кажется, не имеет запланированного эффекта. Мой код (для самого JSpinner) выглядит следующим образом:
spinner.addFocusListener(new FocusAdapter(){
@Override
public void focusGained(FocusEvent e) {
((DefaultEditor) ((JSpinner) e.getSource()).getEditor()).getTextField().selectAll();
}
});
Я не уверен, в чем проблема. Если это имеет значение, я использую Mac OS 10.7.5 и Java 6u43.
EDIT: я поставил System.out.println
прямо в начале метода focusGained и обнаружил, что он никогда не вызывался. Так что похоже, что фокусировка на JSpinner не регистрируется. Опять же, я попытался поместить focusAdpater как на спиннер, так и на текстовое поле (хотя и не одновременно).
2 ответа:
Большая часть проблемы, с которой вы сталкиваетесь, связана с тем, как счетчик проверяет любые значения в счетчике после события фокусировки (и нескольких других событий состояния), которые будут обходить выделение.
MacOS еще хуже.
В итоге я запустилThread
, который ждал очень короткий промежуток времени (около 25 миллисекунд), а затем использовалSwingUtilities.invokeLater
для фактического выполнения выбора...Обновлено с помощью примера
import java.awt.Component; import java.awt.EventQueue; import java.awt.GridBagLayout; import java.awt.event.FocusAdapter; import java.awt.event.FocusEvent; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.text.JTextComponent; public class AutoFocusSpinner { public static void main(String[] args) { new AutoFocusSpinner(); } public static final SelectOnFocusGainedHandler SHARED_INSTANCE = new SelectOnFocusGainedHandler(); public AutoFocusSpinner() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 0, 100, 1)); installFocusListener(spinner); JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new GridBagLayout()); frame.add(spinner); frame.add(new JButton("Here for testing")); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public void installFocusListener(JSpinner spinner) { JComponent spinnerEditor = spinner.getEditor(); if (spinnerEditor != null) { // This is me spending a few days trying to make this work and // eventually throwing a hissy fit and just grabbing all the // JTextComponent components contained within the editor.... List<JTextComponent> lstChildren = findAllChildren(spinner, JTextComponent.class); if (lstChildren != null && lstChildren.size() > 0) { JTextComponent editor = lstChildren.get(0); editor.addFocusListener(SHARED_INSTANCE); } } } public static <T extends Component> List<T> findAllChildren(JComponent component, Class<T> clazz) { List<T> lstChildren = new ArrayList<T>(5); for (Component comp : component.getComponents()) { if (clazz.isInstance(comp)) { lstChildren.add((T) comp); } else if (comp instanceof JComponent) { lstChildren.addAll(findAllChildren((JComponent) comp, clazz)); } } return Collections.unmodifiableList(lstChildren); } public static class SelectOnFocusGainedHandler extends FocusAdapter { @Override public void focusGained(FocusEvent e) { Component comp = e.getComponent(); if (comp instanceof JTextComponent) { final JTextComponent textComponent = (JTextComponent) comp; new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(25); } catch (InterruptedException ex) { } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { textComponent.selectAll(); } }); } }).start(); } } } }
Сейчас, прямо сейчас, Я молюсь о каком-то действительно хорошем, простом, недокументированном свойстве, которое мы можем установить, что будет означать, что нам не нужно делать все это :P
Не знаю, как насчет Mac, но я использовал этот код в Windows:
JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor)spinner.getEditor(); JTextField textField = editor.getTextField(); textField.addFocusListener( new FocusAdapter() { public void focusGained(final FocusEvent e) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JTextField tf = (JTextField)e.getSource(); tf.selectAll(); } }); } });
Я также использовал этот код для выбора текста в поле JFormattedTextField.