Модальный QProgressDialog::setValue() вызывает сбой вложенным циклом событий

Я только что написал некоторый код на основе QThread, который выполняет большие вычисления. Чтобы визуализировать прогресс, мне нужно открыть QProgressDialog. Диалог является модальным приложения (с использованием open ()), так как я не хочу разрешать изменения главного окна во время расчета. Поток испускает различные сигналы, которые позволяют конечному автомату связываться между GUI и потоком.

Два из сигналов, излучаемых рабочим объектом потока, - это "Progress" и "Finished". Если выдается "Progress", я обновляю QProgressDialog, используя setValue(). Если выбрано "Готово", диалог уничтожается.

В конце расчета происходит следующее:

  • Событие "Прогресс" (100%) выброшено
  • "Готово" испускается сразу после
  • setValue(100) вызывается из-за события "Progress"
  • Поскольку диалог модальный, setValue() вызывает processEvents()
  • processEvents() доставляет событие "Завершено"
  • Событие "Завершено" приводит к разрушению диалога в середине setValue (), что вызывает сбой

QProgressDialog ломает мою архитектуру, вызывая processEvents() в setValue(). Также мои соглашения о кодировании запрещают использование любых вложенных циклов событий (как в exec() и т. Д.).

У меня есть два вопроса:

  1. Почему модальный диалог требует вложенного цикла событий? Из моего непонимания блокирование ввода родительских окон, кажется, не требует этого.

  2. Можно ли использовать QProgressDialog модальным способом, но без вложенного цикла событий?

1 ответ

Решение

Ты должен использовать deleteLater() уничтожить твой QProgressDialog, Событие, которое удаляет ваш QProgressDialog Объект обрабатывается в функции, которая принадлежит QProgressDialog Сам объект, это сводится к законности вызова delete this; внутри функции-члена C++ вы можете обратиться к этому вопросу из FAQ по isocpp C++ для получения дополнительной информации об этом. Суть в том, что вы должны гарантировать, что вы больше не получите доступ к любому члену объекта после совершения самоубийства...

так как вы не можете гарантировать это в Qt's QProgressDialog::setValue() реализация, событие, которое deleteс QProgressBar как это будет счастливо вызывать UB при следующем доступе к любому члену объекта (когда поднят в функции-члене). deleteLater был специально разработан для решения этой проблемы, поскольку события отложенного удаления обрабатываются особым образом (они не обрабатываются QCoreApplication::processEvents()). Это означает, что QProgressDialog объект будет уничтожен после setValue возвращает управление в цикл событий, а не в середине выполнения setValue...

Всегда используйте deleteLater в таких ситуациях При использовании равнины delete внутри события вы должны убедиться, что это событие не обрабатывается при выполнении функции-члена этого объекта, и что оно не выполняется в результате испускания сигнала от этого объекта (с прямым сигналом / слот соединения), поскольку, в конце концов, сигнал - это просто функция-член, реализация которой обеспечивается MOC Qt)...

Другие вопросы по тегам