Качать:Есть ли способ отличить событие ItemEvent, вызванное пользователем, от события, вызванного приложением?

StackOverflow https://stackoverflow.com/questions/176150

Вопрос

Я работаю с полем со списком в приложении на основе Swing, и мне трудно понять, что делать, чтобы отличить ItemEvent, созданный из пользовательского события, от события, вызванного приложением.

Например, допустим, у меня есть поле со списком: 'combo' и я слушаю события itemStateChanged с помощью моего ItemListener, 'listener'.Когда пользователь меняет выбор на элемент 2 или я выполняю строку (псевдокод):

combo.setSelection(2)

..кажется, я не могу отличить эти события друг от друга.

Тем не менее, я ни в коем случае не эксперт по Swing, поэтому решил спросить.

Спасибо!

Это было полезно?

Решение

Закон действия и противодействия вполне ясен :).Если вы попытаетесь отреагировать на изменения, нет необходимости различать пользователя и приложение.Я могу себе представить только один вариант использования, где нужно «отличить».Случай, когда приложение отображает некоторые данные.В этом случае у вас, вероятно, есть модель данных для вашего приложения.А также в этой модели есть некоторые прослушиватели изменений, и графический интерфейс приложения будет реагировать, устанавливая значения для компонентов.А также.Если пользователь выбирает что-либо в компоненте графического интерфейса.Модель данных отреагирует изменением значения.В этом случае легко настроить в модели данных какое-то состояние «только для чтения», которое будет уведомлять модель о необходимости игнорировать ЛЮБОЕ событие, исходящее от наблюдаемых объектов.Этот набор уведомлений должен работать в EDT, и с пометкой проблем не возникнет.Небольшой пример:

class ApplicationDataModel {

    private Flag current = Flag.RW;

    public void setData(ApplicationData data) {
        current = Flag.RO;
        setDataImpl(data);
        notifyObservers();
        current = Flag.RW;
    }

    public void reaction(Event e) {
        if (flag = Flag.RO) return;
        ...
    }

}

Будьте осторожны с пометкой и не забывайте о многопоточности.Если вы вызываете setData из другого потока, тогда EDT у вас возникнут проблемы.Конечно.Добыча ApplicationData объект должен быть запущен в другом потоке;).В общем, переосмыслите дизайн своего приложения.

Другие советы

Независимо от того, выбирает ли пользователь элемент 2 или API вызывает setSelection(2), событие будет выглядеть так же.

Решение вашей проблемы может заключаться в переосмыслении того, что вы хотите, чтобы код itemStateChanged делал при изменении выбора.Почему ваше приложение будет работать по-разному при каждом условии?Возможно, есть сходства, которые вы можете использовать в своих интересах.

Будьте осторожны при использовании флагов.Событие itemStateChanged произойдет в потоке диспетчеризации событий, который отличается от того, в котором вы установили состояние флага.Это будет означать, что использование флага не может быть на 100% надежным.

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

Возможно, со времен Java 6 есть лучший способ, но я всегда делал это именно так...

[Редактировать]:Как указывает Дэвид, вам нужно будет установить флаг (и обновить комбинацию) в EDT, используя SwingUtilities.invokeLater или аналогичный (вам все равно следует это сделать, поскольку вы меняете элемент управления пользовательского интерфейса).

Если вам нужно различить события, возможно, в вашем дизайне есть что-то, что нужно переосмыслить.Вся суть MVC заключается в том, чтобы отделить изменения модели от реальных щелчков мыши пользователя.

Возможно, вам следует переформулировать вопрос с точки зрения почему вам когда-нибудь захочется провести различие между этими двумя ситуациями.Затем мы могли бы дать некоторые рекомендации по другому пути достижения цели.

Итак, я предполагаю, что вы хотите, чтобы выбор пользователя выполнял какое-то действие, а не просто старое прямое изменение состояния.Это проблема, вызванная ограниченной гибкостью (гибкость всегда будет ограничена, особенно если у вас есть гибкость в других направлениях).

Мое предложение:

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

Распространенной практикой является делегирование между моделями.Итак, в этом случае у вас есть «настоящая» модель по умолчанию, в которой хранятся ваши данные.Вставьте между JComboBox и реальной ComboBoxModel и делегируйте ComboBoxModel, который выполняет действия по инструкциям по изменению состояния.Код вашего приложения должен игнорировать JComboBox и сразу перейти к реальной ComboBoxModel, минуя модель делегирования.Итак, на схеме:

User -- JComboBox -- ActionComboBoxModel -- DefaultComboBoxModel -- Application code
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top