#java #swing #keystrokes
#java #swing #нажатия клавиш
Вопрос:
Я читал о регистрации объектов «Action» с несколькими компонентами, и я наткнулся на рецепт регистрации (привязки) объекта Action к объекту нажатия клавиши.
В процессе поиска я наткнулся на этот фрагмент кода:
InputMap imap = panel.getInputMap(JComponent.WHEN_FOCUSED);
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
ActionMap amap = panel.getActionMap();
amap.put("panel.yellow", yellowAction)
Теперь способ, которым это работает, заключается в том, что существует один уровень косвенности для регистрации ваших нажатий клавиш с объектами Action. Во-первых, вы связываете нажатие клавиши с некоторым произвольным объектом на одной из входных карт (в нашем примере это карта, соответствующая константе WHEN_FOCUSED) Компонента, и, во-вторых, вы регистрируете действие с той же ссылкой на другой карте, ActionMap, поддерживаемой компонентом.
Теперь я сомневаюсь в том, что, если я предполагаю, что семантика сопоставления нажатия клавиши с объектами действия выполняется с использованием сходства ссылки на промежуточный объект, находящейся на этих двух картах, то где гарантия, что это равенство будет выполняться всегда, если только ссылка на объект, которую я использовал, действительно не определяет действительное понятие равенства (или хэш-код).
Например, в моем примере я прикрепляю нажатие клавиши к экземпляру String «panel.желтый «в одной из входных карт, затем я пытаюсь прикрепить объект action с той же строкой «панель.желтый » в ActionMap панели. Теперь, теоретически, JVM не гарантирует, что оба этих экземпляра String (которые я жестко запрограммировал) будут ссылаться на один и тот же объект String! И что еще хуже, если JVM не предоставляет понятие равенства содержимого для строк, то нет никакого способа, чтобы мой объект action мог быть успешно сопоставлен с моим нажатием клавиши. Это так же верно для любого объекта, который я могу использовать для промежуточной привязки нажатия клавиши к объектам действия, и для которого я не определил никакого понятия равенства (или хэш-кода), кроме ссылочного равенства, которое определяет класс Object.
Кто-нибудь, пожалуйста, может прояснить это.
AViD
Ответ №1:
Вы правы в том, что обе строки могут не быть одним и тем же объектом, но вы можете проверить равенство, используя equals(...)
метод, который, вероятно, будет использоваться для сопоставления вашего действия с нажатием клавиши.
Обратите внимание, что кроме того, hashCode
каждый объект также предоставляет equals(...)
метод, который может быть таким же, как ==
для произвольных объектов, но String
переопределяет его для проверки равенства содержимого (что вы также сделали бы, если бы переопределили этот метод для пользовательских объектов).
Комментарии:
1. но тогда возникает вопрос, что, если значение equals не переопределяется? тогда как промежуточный объект сопоставляет нажатие клавиши с объектом Action. Хуже всего то, что это нигде не задокументировано при использовании метода 🙁 Я имею в виду, что это поведение (переопределяющее равенство) должно применяться для произвольных объектов, иначе я могу выбрать неправильный тип объекта для отображения. Для меня это будет очень сложная ошибка для поиска.
2. Если вы прочитаете JavaDoc
equals
метода, вы найдете соглашение о том, что каждый объект, являющийся ключом в некоторой коллекции, должен переопределятьequals
иhashCode
. В противном случае объекты могут не считаться равными. Если вы используете пользовательские объекты, вы несете ответственность за определение равенства, а если вы используете встроенные объекты, такие какString
,Integer
и т.д. вы можете доверять Sun / Oracle в том, что у них есть разумное определение равенства этих объектов.3. «Я имею в виду, что это поведение (переопределяющее равенство) должно применяться для произвольных объектов, иначе я могу выбрать неправильный тип объекта для отображения. Для меня это будет очень сложная ошибка для поиска.» — Компилятор не применяет это, но существуют такие инструменты, как checkstyle или findbugs, которые могут помочь вам в этом.
Ответ №2:
Строки интернированы по умолчанию, поэтому они будут одним и тем же объектом. Смотрите метод String.intern () для получения дополнительной информации.
Но если вы действительно обеспокоены этим, то простым решением является использование одной и той же ссылки на объект в InputMap и ActionMap.
Ознакомьтесь с примером кода из Key Bindings, который показывает, как я это делаю.
Комментарии:
1. Да, использование той же ссылки на объект будет лучшим выбором. — AViD