Подтвердить что ты не робот

Разрушение циклов событий в графических интерфейсах

При написании графических интерфейсов я часто сталкиваюсь со следующей проблемой: предположим, что у вас есть модель и контроллер. Контроллер имеет виджет W, который используется для отображения свойства X модели.

Поскольку модель может быть изменена извне контроллера (могут быть другие контроллеры, использующие одну и ту же модель, операции отмены и т.д.), контроллер прослушивает изменения в модели. Контроллер также прослушивает события в виджете W и соответственно обновляет свойство X.

Теперь происходит следующее:

  • изменяется значение в W
  • генерируется событие, вызывается обработчик в контроллере
  • контроллер устанавливает новое значение для X в модели
  • модель излучает события, потому что она была изменена.
  • контроллер получает событие изменения из модели
  • контроллер получает значение X и устанавливает его в виджет
  • перейти 1.

Для этого существует несколько возможных решений:

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

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

Только для записи у меня была эта проблема с несколькими инструментами GUI, включая GTK +, Qt и SWT, поэтому я думаю, что это довольно инструментарий-агностик.

Любые лучшие практики? Или архитектура, которую я использую просто неправильно?

@Shy: это решение для некоторых случаев, но вы по-прежнему получаете раунд лишних событий, если X изменен извне контроллера (например, при использовании шаблона команды для отмены/повтора), потому что тогда значение изменилось, W обновлено и запускает событие. Чтобы предотвратить другое (бесполезное) обновление модели, событие, генерируемое виджетами, должно быть проглочено.
В других случаях модель может быть более сложной, и простая проверка того, что именно изменилось, может оказаться невозможной, например. сложное древовидное представление.

4b9b3361

Ответ 1

Обычно вы должны отвечать на события ввода в виджетах и ​​не изменять события. Это предотвращает появление этого типа цикла.

  • Пользователь вводит изменения в виджет
  • Виджет испускает событие изменения (прокрутка выполняется/вводится щелчок мыши/удержание мыши и т.д.).
  • Контроллер отвечает, переводит на изменение в модели
  • Модель испускает событие
  • Контроллер отвечает, изменяет значение в виджетах
  • Событие изменения значения выбрано, но не прослушивается контроллером.

Ответ 2

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

см. этот учебник

Ответ 3

Флаги для указания работы по обновлению. Вы можете обернуть их такими методами, как BeginUpdate и EndUpdate.