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

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

  •  02-07-2019
  •  | 
  •  

Вопрос

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

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

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

  1. значение в W изменен
  2. генерируется событие, обработчик в контроллер вызывается
  3. тот самый контроллер устанавливает новое значение для X в Модель
  4. тот самый Модель генерирует события, потому что они были изменены
  5. тот самый контроллер получает событие изменения от Модель
  6. тот самый контроллер получает значение X и устанавливает его в виджете
  7. переход 1.

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

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

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

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

Есть какие-нибудь рекомендации?Или архитектура, которую я использую, просто неправильная?

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

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

Решение

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

  1. Пользователь изменяет вводимые данные в виджете
  2. Виджет выдает событие изменения (прокрутка завершена / нажат ввод / оставлена кнопка мыши и т.д.)
  3. Контроллер реагирует, преобразуя изменения в модели
  4. Модель генерирует событие
  5. Контроллер реагирует, изменяя значение в виджете
  6. Событие изменения значения, отправленное, но не прослушанное контроллером

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

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

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

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

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