Существует ли простой способ изменить поведение управления Java/Swing, когда это получает фокус?

Когда вы объявляете ссылочную переменную (т. е. объект), вы действительно создаете указатель на объект. Рассмотрим следующий код, в котором вы объявляете переменную примитивного типа int:

int x;
x = 10;

В этом примере переменная x является int, и Java инициализирует ее для 0. Когда вы назначаете его 10 во второй строке, ваше значение 10 записывается в ячейку памяти, на которую указывает x.

Но когда вы пытаетесь объявить ссылочный тип, произойдет что-то другое. Возьмите следующий код:

Integer num;
num = new Integer(10);

Первая строка объявляет переменную с именем num, но она не содержит примитивного значения. Вместо этого он содержит указатель (потому что тип Integer является ссылочным типом). Поскольку вы еще не указали, что указать на Java, он устанавливает значение null, что означает «Я ничего не указываю».

Во второй строке ключевое слово new используется для создания экземпляра (или создания ) объекту типа Integer и переменной указателя num присваивается этот объект. Теперь вы можете ссылаться на объект, используя оператор разыменования . (точка).

Exception, о котором вы просили, возникает, когда вы объявляете переменную, но не создавали объект. Если вы попытаетесь разыменовать num. Перед созданием объекта вы получите NullPointerException. В самых тривиальных случаях компилятор поймает проблему и сообщит вам, что «num не может быть инициализирован», но иногда вы пишете код, который непосредственно не создает объект.

Например, вы можете имеют следующий метод:

public void doSomething(SomeObject obj) {
   //do something to obj
}

В этом случае вы не создаете объект obj, скорее предполагая, что он был создан до вызова метода doSomething. К сожалению, этот метод можно вызвать следующим образом:

doSomething(null);

В этом случае obj имеет значение null. Если метод предназначен для того, чтобы что-то сделать для переданного объекта, целесообразно бросить NullPointerException, потому что это ошибка программиста, и программисту понадобится эта информация для целей отладки.

Альтернативно, там могут быть случаи, когда цель метода заключается не только в том, чтобы работать с переданным в объекте, и поэтому нулевой параметр может быть приемлемым. В этом случае вам нужно будет проверить нулевой параметр и вести себя по-другому. Вы также должны объяснить это в документации. Например, doSomething может быть записано как:

/**
  * @param obj An optional foo for ____. May be null, in which case 
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj != null) {
       //do something
    } else {
       //do something else
    }
}

Наконец, Как определить исключение & amp; причина использования Трассировки стека

7
задан Dale Wilson 17 September 2008 в 18:19
поделиться

5 ответов

После чтения ответов до сих пор (Спасибо!) я передал наиболее удаленный JPanel следующему методу:

void addTextFocusSelect(JComponent component){
    if(component instanceof JTextComponent){
        component.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent event) {
                    super.focusGained(event);
                    JTextComponent component = (JTextComponent)event.getComponent();
                    // a trick I found on JavaRanch.com
                    // Without this, some components don't honor selectAll
                    component.setText(component.getText());
                    component.selectAll();
                }
            });

    }
    else
    {
        for(Component child: component.getComponents()){
            if(child instanceof JComponent){
                addTextFocusSelect((JComponent) child);
            }
        }
    }
}

Работает!

1
ответ дан 7 December 2019 в 07:53
поделиться

Когда мне было нужно это в прошлом, я создал подклассы компонентов, я хотел добавить "автоочищающуюся" функциональность также. например:

public class AutoClearingTextField extends JTextField {
   final FocusListener AUTO_CLEARING_LISTENER = new FocusListener(){
      @Override
      public void focusLost(FocusEvent e) {
         //onFocusLost(e);
      }

      @Override
      public void focusGained(FocusEvent e) {
         selectAll();
      }
   };

   public AutoClearingTextField(String string) {
      super(string);
      addListener();
   }

   private void addListener() {
      addFocusListener(AUTO_CLEARING_LISTENER);      
   }
}

Самая большая проблема состоит в том, что я не нашел "хороший" способ получить всех типичных конструкторов, не пишущий переопределения. Добавление их и принуждение вызова к addListener являются наиболее общим подходом, который я нашел.

Другая опция состоит в том, чтобы наблюдать за ContainerEvents на контейнере верхнего уровня с ContainerListeer, чтобы обнаружить присутствие новых виджетов и добавить соответствующего слушателя фокуса на основе виджетов, которые были добавлены. (например: если контейнерное событие вызывается путем добавления TextField, то добавьте слушателя фокуса, который знает, как выбрать весь текст в TextField и так далее.), Если Контейнер добавляется, то необходимо рекурсивно добавить ContainerListener к тому новому подконтейнеру также.

Так или иначе Вы не должны будете слоняться без дела со слушателями фокуса в своем фактическом коде UI - он будет все заботиться о в более высоком уровне.

2
ответ дан 7 December 2019 в 07:53
поделиться

Я не попробовал это сам (только баловался им только что), но можно, вероятно, получить текущий сфокусированный компонент при помощи: KeyboardFocusManager (существует статический метод getCurrentKeyboardFocusManager ()), добавление PropertyChangeListener к нему. Оттуда, можно узнать, является ли компонентом JTextComponent, и выберите весь текст.

2
ответ дан 7 December 2019 в 07:53
поделиться

Отдельный класс, который присоединяет FocusListener к полю требуемого текста, может быть записан. Весь слушатель фокуса сделал бы, назвать selectAll () на текстовом виджете, когда он получает фокус.

public class SelectAllListener implements FocusListener {
  private static INSTANCE = new SelectAllListener();

  public void focusLost(FocusEvent e) { }

  public void focusGained(FocusEvent e) {
    if (e.getSource() instanceof JTextComponent) {  
      ((JTextComponent)e.getSource()).selectAll();
    }
  };

  public static void addSelectAllListener(JTextComponent tc) {
    tc.addFocusListener(INSTANCE);
  }

  public static void removeSelectAllListener(JTextComponent tc) {
    tc.removeFocusListener(INSTANCE);
  }
}

Путем принятия JTextComponent как аргумент это поведение может быть добавлено к JTextArea, JPasswordField и всем другим компонентам редактирования текста непосредственно. Это также позволяет классу добавлять выбор все к доступным для редактирования полям комбинированного списка и JSpinners, где Ваше управление компонентом текстового редактора может быть более ограничено. Удобные методы могут быть добавлены:

public static void addSelectAllListener(JSpinner spin) {
  if (spin.getEditor() instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)spin.getEditor());
  }
}

public static void addSelectAllListener(JComboBox combo) {
  JComponent editor = combo.getEditor().getEditorComponent();
  if (editor instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)editor);
  }
}

Кроме того, удалить методы прослушивателя являются, вероятно, ненужными, так как слушатель не содержит внешних ссылок ни на какие другие экземпляры, но они могут быть добавлены, чтобы заставить обзоры кода пойти более гладкие.

2
ответ дан 7 December 2019 в 07:53
поделиться

Единственным путем я знаю, должен создать FocusListener и присоединить его к Вашему компоненту. Если Вы хотите, чтобы это этот FocusListener было глобально ко всем компонентам в Вашем приложении, Вы могли бы рассмотреть использование Аспектно-ориентированного программирования (AOP). С AOP возможно кодировать его однажды и применить Вашего слушателя фокуса всех компонентов, которые инстанцируют в Вашем приложении, не имея необходимость к копии-и-вставке component.addFocusListener (слушатель) код всюду по Вашему приложению..

Ваш аспект должен был бы прервать создание JComponent (или подклассы, Вы хотите добавить это поведение к), и добавьте слушателя фокуса недавно созданного экземпляра. Подход AOP лучше, чем копия-и-вставка FocusListener к Вашему всему коду, потому что Вы сохраняете все это в единственной части кода и не создаете кошмар обслуживания, после того как Вы решаете изменить свое глобальное поведение как удаление слушателя для JSpinners.

Существует много платформ AOP там для выбора из. Мне нравится JBossAOP, так как это - 100%-й чистый Java, но Вы хотели бы смотреть на AspectJ.

0
ответ дан 7 December 2019 в 07:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: