Лучший подход для действия с двойным состоянием
-
13-09-2019 - |
Вопрос
Недавно я реализовал Action
который переключает включенный статус бизнес-функции.Всякий раз, когда пользователь вызывает действие, я устанавливаю логический флаг:"будетВключить", чтобы определить, включит или отключит функцию следующий вызов.Аналогичным образом я обновляю имя действия, краткое описание и значок, чтобы отразить новое состояние.Тогда в моем actionPerformed(...)
метод, я предпринимаю разные действия в зависимости от состояния willEnable
.
- Является ли это правильным подходом или кто -нибудь может порекомендовать лучший (как я подозреваю, это общая проблема)?(Я вижу
JToggleButton
действует как кнопка с двумя государствами, но я хочу, чтобы это действие было видно наJMenuBar
также как иJButton
, поэтому не думайте, что это уместно).
РЕДАКТИРОВАТЬ
В частности, как с этим справляются такие приложения, как IDEA?Будут ли они использовать действия с несколькими состояниями (как указано выше) или поменяют местами другой Action
в заданный JButton
с использованием setAction(Action)
?Возможно, этот подход лучше?
- При обновлении свойств действия я могу полагаться на компоненты графического интерфейса, инициализированные с этим
Action
(например.JButton
) автоматически перекрасить себя?Что, еслиJButton
в результате размер изменится?Должен ли я переоценивать содержаниеJPanel
сам? - Изменение имени действия - плохое занятие?Это единственный способ, которым я могу внести изменение текста Jbutton, но я осознаю, что имя, вероятно, должно оставаться постоянным, если действие помещается в
ActionMap
.
Заранее спасибо.
Решение
Я ожидаю, что любой компонент графического интерфейса, созданный с использованием некоторой «модели» данных (я бы включил Action
как модель данных) должен зарегистрироваться в качестве прослушивателя этой модели.Это должен принять соответствующие, хм, меры по PropertyChangeEvent
быть уволенным:По моему мнению, любое другое поведение будет представлять собой ошибку.
Сомнительно здесь то, правомерно ли менять название акции;я думаю что это не законно.Ваше действие логически ToggleEnabledStatus и это не меняется, поскольку действие было вызвано.Любой компонент, которому необходимо отображать любой другой текст, должен зарегистрироваться в качестве прослушивателя Action
а затем проверь свой willEnable
флаг, чтобы предпринять соответствующие, эээ, действия.
В качестве альтернативы вы можете написать свой собственный класс, реализующий ToggleButtonModel
и Action
в то же время и контролировал события изменений изнутри.Однако это очень много кода, а пользы мало.
Другие советы
Возможно, вы захотите посмотреть Образец состояния.
По сути, вы создаете интерфейс и две (или более) его реализации для каждого состояния.В качестве простого примера: состояние отключения может просто реализовать интерфейс, чтобы ничего не делать, в то время как состояние включения выполняет некоторые действия.Чтобы переключить состояние, вы просто сделаете
interface IState {
void doAction();
boolean isEnabled();
}
class EnabledState implement IState {
void doAction() {
setState(new DisabledState());
// do something
}
boolean isEnabled() {return true;}
}
class DisabledState implement IState {
void doAction() {
setState(new EnabledState());
// do nothing
}
boolean isEnabled() {return false;}
}
private IState state = new DisabledState(); // default is disabled
private PropertyChangeSupport support = new PropertyChangeSupport(this);
void setState(IState state) {
if (this.state != state) {
IState oldState = this.state;
this.state = state;
support.firePropertyChange("enabled", oldState.isEnabled(), state.isEnabled());
}
}
void doAction() {
state.doAction();
}
Хотя это немного накладно для одного метода, оно, безусловно, окупится, как только у вас появится несколько методов, которые изменяют его поведение в зависимости от одного состояния.