Изменение размера/перемещение окна QML
Я разрабатываю простое приложение QML
прямо сейчас, и я заметил, что изменение размера и перемещение окна QML
генерирует уродливое мерцание по сравнению с окном QtWidgets
, например.
Итак, я создал 2 тестовых приложения, чтобы показать разницу:
QWidgets:
![enter image description here]()
QML:
![enter image description here]()
Как видите, версия приложения QML
мерцает довольно уродливо, а QtWidgets
- чистая. Теперь это становится довольно уродливым, когда ваш пользовательский интерфейс растет с трудом.
Есть ли у вас какие-либо знания об этом? Это ошибка? Есть ли исправление/обходное решение для этой проблемы?
Ответы
Ответ 1
Вы можете попробовать следующее:
int main(int argc, char* argv[]) {
QCoreApplication::setAttribute(Qt::AA_UseOpenGLES);
or
QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
Первый вариант использует библиотеку углов OpenGl2DirecX (например, Google Chrome).
Второй использует эмуляцию OpenGL с помощью программного обеспечения... для небольших программ работает очень хорошо и на 100% совместимо со старой ОС, такой как Windows XP.
Примечание. Вы можете попробовать с Qt 5.7, а новый Qtquick.Controls 2.0... работает намного лучше...
https://blog.qt.io/blog/2016/06/10/qt-quick-controls-2-0-a-new-beginning/
Ответ 2
В моем случае я решил это, добавив следующий флаг:
QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);
Но это добавит другие проблемы с рендерингом. Или нет.
Ответ 3
Проблема с изменением размера приложений QML заключается в обновлении окна с устаревшей геометрией. Исправление будет заключаться в синхронизации обновлений и изменения размера.
Так как могут быть внезапные обновления от таймера обновления для визуализации графа сцены, который может обновлять окно в любое время, это вызывает рисование содержимого с устаревшей геометрией. https://bugreports.qt.io/browse/QTBUG-46074
Для синхронизации изменения размера и обновления окна следует использовать либо базовую, либо расширенную синхронизацию. В настоящее время базовая синхронизация используется и реализована в Qt, но все же необходимо синхронизировать обновления окна (из таймера) с событиями изменения размера из Windows Manager.
Но, как всегда, есть список вопросов:
Проблема наблюдается, когда размер окна изменяется слишком быстро. Поскольку синхронизация событий (от WM) должна отправляться последовательно, следующий за предыдущим:
-
<= _NET_WM_SYNC_REQUEST отправлено с WM, размер сейчас меняется.
-
_NET_WM_SYNC_REQUEST получено и обработано приложением.
-
<= получены некоторые другие события, например новая геометрия.
-
.. обновить содержимое, swapBuffers.
-
=> Отправлено _NET_WM_SYNC_REQUEST_COUNTER обратно в WM.
-
<= _NET_WM_SYNC_REQUEST снова отправляется с WM, размер меняется.
-
.. swapBuffers//здесь проблема, обновление выполняется, когда окно меняет свою геометрию.
-
_NET_WM_SYNC_REQUEST получен и обработан снова.
Таким образом, проблема возникает, когда (7) swapBuffers появляется после того, как _NET_WM_SYNC_REQUEST отправлено, но еще не получено/обработано.
И напоследок вывод:
- Фактическое изменение размера окна начинается сразу после отправки _NET_WM_SYNC_REQUEST Диспетчером окон. И не когда приложение получит его. В это время окно может быть даже обновлено, когда запрос на синхронизацию отправляется, но еще не обрабатывается приложением. Который будет рисовать контент с устаревшей геометрией.
- _NET_WM_FRAME_DRAWN может помочь в синхронизации между изменением размера и обновлениями, но также может не поддерживаться (и предполагаю, что это не так) диспетчером окон.
Другими словами, базовая или расширенная синхронизация не помогает (по крайней мере, без _NET_WM_FRAME_DRAWN), потому что нет способа узнать, когда фактическое изменение размера выполнено.
Расширенный протокол синхронизации - это попытка справиться с этим, но поскольку фактическое изменение геометрии выполняется без синхронизации с клиентом, как я вижу, без _NET_WM_FRAME_DRAWN всегда есть возможность обновить окно устаревшей геометрией.
https://lists.freedesktop.org/archives/xcb/2019-February/011280.html