Прерывание циклов событий в графическом интерфейсе - PullRequest
17 голосов
/ 24 сентября 2008

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

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

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

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

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

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

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

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

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

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

Ответы [ 3 ]

5 голосов
/ 24 сентября 2008

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

см. Этот урок

3 голосов
/ 24 сентября 2008

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...