Вступление:
Я пишу приложение, которое отображает список пользовательских QWidget (а именно, «ScopeWidget») в контейнерном виджете с VBoxlayout («ScopeView»).
Каждый scopeWidget имеет указатель на собственный класс источника данных («Scope»). Эти объекты логически сгруппированы в группы, то есть есть несколько общих параметров («ScopeShared») среди объектов в одной группе.
Эти параметры необходимы при получении (или подготовке) данных, которые должны отображаться в scopeWidget.
На шаг впереди:
Область виджетов нуждается в двух наборах параметров: эти задаются «Scope» и «ScopeGroup».
Область действия виджета может с помощью действий пользователя изменять некоторые общие параметры в группе, тем самым аннулируя все предыдущие извлеченные данные, которые хранятся в «Scope» в этой группе.
По умолчанию в «Scope» нет отображаемых данных. Данные извлекаются по запросу — когда происходит событие paintEvent (это является источником проблемы). Чтобы получить отображаемые данные в «Области», необходимо обработать все «Области» в этой конкретной группе (что дает пригодные для использования данные для всех «Области» в группе).
Как это устроено:
Пользователь заставляет один из scopeWidgets изменить общие данные в группе. После внесения этих изменений все данные, хранящиеся в «Scope» в этой группе, становятся недействительными, поэтому событие изменения повторно обрабатывает всю группу. И вызывает update () для всех scopeWidgets в этой группе. Виджеты перерисованы. Это работает…
Эта проблема:
… Событие, которое произошло спонтанно. Когда пользователь что-то меняет — я знаю, что это произошло, и я могу обработать scopeGroup до постановки в очередь обновлений виджетов. Но когда «что-то еще» (сама система) выполняет событие рисования, I_need обрабатывает всю группу до того, как произойдет рисование.
Таким образом, событие рисования не выполняет рисование напрямую, но выполняет обработку scopeGroup, и после этого оно рисует виджет, у которого было событие рисования, и вызывает update () для всех других виджетов в этой группе, что, в свою очередь, вызывает новые события рисования, которые вызвать следующую обработку scopeGroup, одну paint () и update () для других виджетов, что вызывает новые события рисования — это заканчивается как рекурсивная перекраска (и обработка scopeGroup)
Хромое решение:
flags — спонтанные события рисования выполняют групповую обработку, один paint () для запрашивающего виджета и update () для остальных виджетов в группе, вместе с установкой флагов для каждого виджета.
Этот псевдокод изображает этот механизм:
paintEvent(QWidget *w)
{
if(w->flag)
{
w->paint(); w->flag=0;
}
else
{
w->group()->process();
w->paint();
QWidget *x;
foreach(x,group) if(x!=w) { x->flag=1; x->update(); }
}
Что было бы ИМХО лучше
а) если виджеты могут быть нарисованы без предварительного события рисования (или вызова update () или repaint ()) … это было бы лучше;], но это не работает прямым и очевидным способом — есть ли другой способ? — или же
б) заставить систему вызывать пользовательскую функцию вместо события рисования
Возможны ли эти «лучшие» решения?
Задача ещё не решена.
Других решений пока нет …