Отзывчивый QGraphicsWidget
Моя проблема - простой, но раздражающий пользовательский опыт, наносящий ущерб. Я пытаюсь отобразить огромное количество (10 тысяч) пользовательских QGraphicsItem
на QGraphicsScene
, Я бы также потребовал QGraphicsLayout
, но, насколько я понимаю, нельзя просто разместить макет на сцене, для этого макет должен быть установлен на QGraphicsWidget
а затем виджет добавлен в сцену.
Теперь, когда мне нужно загрузить большое количество элементов и подготовить их к отображению, сцена просто остается пустой, потому что я не могу сделать недействительным или перекрасить вышеупомянутое. QGraphicsWidget
, Только в конце он может быть добавлен в сцену, иначе дальнейшие изменения не будут отображены.
Цель: добавить некое управление макетом в сцену -> {подготовить элемент -> добавить элемент в макет -> отобразить -> подготовить элемент ->} повторить...
Но что у меня есть: {подготовить элемент -> подготовить другой элемент ->} повторить... -> добавить все в макет -> установить управление макетом на сцене -> отобразить
Итак, вопрос: каким образом можно создать адаптивный макет / контейнер для сцены, который перерисовывается после добавления нового дочернего элемента?
2 ответа
Из руководства Qt:
Когда сцена изменяется (например, когда элемент перемещается или трансформируется), QGraphicsScene испускает сигнал change ().
Здесь не упоминается о addItem() и removeItem(). Надеюсь, они также покрыты.
Если это так, вы можете применить следующее:
Обработчик сигнала может "поймать" изменение и запросить перерисовку (например, invalidate ()) сцены. (Не-) К счастью, это не сразу перерисовывает сцену (с ее родительским представлением), но ставит в очередь событие перерисовки. Таким образом, реальная перерисовка не выполняется до тех пор, пока цикл обработки не будет снова пройден
(Цикл обработки событий является частью QApplication. Если вы остановите свое приложение внутри команды, инициированной пользовательским интерфейсом, вы найдете в стеке вызовов что-то вроде этого:
Qt5Cored.dll!QEventLoop::processEvents(QFlags<enum QEventLoop::ProcessEventsFlag> flags)
Qt5Cored.dll!QEventLoop::exec(QFlags<enum QEventLoop::ProcessEventsFlag> flags)
Qt5Cored.dll!QCoreApplication::exec()
)
Вы можете форсировать это, вызывая QApplication::processEvents(). (Это даже статично.) AFAIK, обычно нет проблем, если циклы событий вложены, потому что они подготовлены для этого (до тех пор, пока не сформирована неразорванная рекурсия).
Тем не менее, это, вероятно, требует некоторой тонкой настройки, потому что слишком много перерисовок может сильно замедлить ваше приложение.
Удалось найти мою ошибку. Это было в пользовательском макете, который я создал для QGraphicsWidget
,
Как сказано в документе о настройке макета:
Все виджеты, которые в данный момент управляются макетом или всеми его подуровнями, автоматически переопределяются в этот элемент. Затем макет становится недействительным, и геометрия дочернего виджета корректируется в соответствии с геометрией этого элемента () и contentsMargins(). Дочерние объекты, которые не управляются явно макетом, остаются вне зависимости от макета после его назначения этому виджету.
После того, как макет был установлен для виджета, любой новый элемент, добавленный в него, не был перерисован в виджете, поэтому он остался неизменным и не отображался.
призвание QGraphicsLayout::addChildLayoutItem(QGraphicsLayoutItem* newItem)
ссылка на каждый элемент, вставленный в макет, решила мою проблему.