Мерцающие белые области при изменении размера окна Qt

Я наблюдаю странное поведение при изменении размера QWindow. Когда я изменяю размер окна так, что ширина и высота увеличиваются или уменьшаются, окно не мерцает белым фоном. Но когда я увеличиваю ширину при уменьшении высоты (или наоборот), окно мерцает и временно заполняет новые области белым цветом. Это очень раздражающий эффект, особенно когда у меня в приложении темная тема и я изменяю размер окна.

Чтобы поэкспериментировать с этим, я использовал пример «растрового окна», входящий в состав Qt SDK. Здесь не используется QtWidgets, поэтому я использовал этот пример, чтобы исключить эффект, вызванный виджетами. Я добавил функцию QThread::msleep(100); к RasterWindow::render(QPainter *), чтобы имитировать очень медленный рендеринг. Затем я попытался изменить размер окна. Я могу наблюдать это только в Windows, но не в Linux или Mac. Смотрите прикрепленный GIF.

Мои вопросы:

  1. Любая идея, что вызывает проблему? Почему только на винде?
  2. Почему его нельзя наблюдать при увеличении как ширины, так и высоты? И почему оно наблюдается при уменьшении одного измерения и увеличении другого?
  3. Как избавиться от этого?
  4. Если я не могу избавиться от него полностью, могу ли я заполнить новую область другим цветом, кроме белого (чтобы это не так сильно раздражало в темной теме)?

ОБНОВЛЕНИЕ: здесь я создал минималистичный пример

/*
This is a minimalistic example to show Qt window flickering on Windows (not observed on Linux nor MacOS).

This is observable ONLY when the window is being resized by dragging lower right (or upper right or lower left) corner
so that one dimension (e.g. width) is increasing and the other dimension (is decreasing).
In that case the newly emerging areas are always filled in with white color which can be observed as terrible flickering.

Curiously the flickering does not happen:
- when you resize the window so that BOTH width and height are increasing
- when you resize the window by dragging the upper left corner

This is not a problem when you have light theme (then window background is probably white anyway).
But this is a big issue when you have dark theme, in which case it is superugly.

Notes:
1) there seems to be the same problem in QtWidgets and QtQuick applications,
   I have not found any Qt application which would behave correctly
2) This is not a problem of Windows OS. Non-Qt applications which I have tested
   seem to behave correctly, i.e. no flickering.
*/

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QThread>

class Widget : public QWidget
{
public:
    Widget()
    {
        /*
        The following code was used for experiments. But nothing worked, I could not get rid of flickering.
        The documentation says:
        autoFillBackground : bool
        This property holds whether the widget background is filled automatically
        If enabled, this property will cause Qt to fill the background of the widget before invoking the paint event.
        The color used is defined by the QPalette::Window color role from the widget's palette.
        */
        //setAttribute(Qt::WA_OpaquePaintEvent, true);
        //setAttribute(Qt::WA_NoSystemBackground, true);
        //setAutoFillBackground(false);
        //QPalette p = palette();
        //p.setColor(QPalette::Window, Qt::blue);
        //setPalette(p);
    }

    void paintEvent(QPaintEvent *) override
    {
        QPainter p(this);
        p.fillRect(0, 0, width(), height(), Qt::blue);
        QThread::msleep(50); // just to simulate slower painting
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

UPDATE2: Я подозреваю, что проблема может быть в QWindowsWindow::handleGeometryChange() см. https://code.woboq.org/qt5/qtbase/src/plugins/platforms/windows/qwindowswindow.cpp.html хотя я не знаю, как почини это. Я сообщил об этой проблеме как об ошибке https://bugreports.qt.io/browse/QTBUG-89688

ОБНОВЛЕНИЕ 3: ошибка исправлена ​​в Qt 6.1. Отличная работа.

Эффект, который вы видите, довольно часто зависит от базовой графической/оконной системы. Когда размер окна изменяется, оно заполняет это окно цветом фона и рисует кэшированное предыдущее содержимое, закрепленное в одном углу (обычно в верхнем левом).

G.M. 24.12.2020 23:01

@G.M. Я пробовал многие не-Qt приложения для Windows, такие как File Explorer, Total Commander, Foobar2000, Notepad++. Ни у кого из них нет такого мерцания. Отсюда я делаю вывод, что это не проблема Windows. Кажется, это проблема Qt, потому что только приложения Qt демонстрируют такое уродливое поведение.

HiFile.app - best file manager 25.12.2020 09:47

@G.M. Я полностью понимаю ваше объяснение, но оно не объясняет, почему оно мерцает только тогда, когда одно измерение увеличивается, а другое уменьшается. И почему он НЕ мерцает, когда оба измерения увеличиваются.

HiFile.app - best file manager 25.12.2020 09:49

Я вижу такое поведение во всех окнах Windows 10 (Проводник, Chrome, Настройки и т. д.). Я думал, что это просто Qt, но это похоже на ошибку Windows 10. Медленно изменяя размер, я могу даже получить постоянные сбои, которые остаются возле краев ветра, пока вы не щелкнете строку заголовка.

Jarrod Smith 07.05.2021 13:23

есть еще несколько случаев, когда вы получите мерцание, см. ошибку bugreports.qt.io/browse/QTBUG-98122. Решение, которое мы нашли, состоит в том, чтобы явно установить GCLP_HBRBACKGROUND на нулевую кисть, чтобы при изменении размера окна цвет заливки не был белым.

lorenzolightsgdwarf 10.11.2021 09:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
5
1 144
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Эта ошибка была исправлена ​​в Qt 6.1. Насколько я проверял, в моих проектах мерцание белых областей исчезло.

ОБНОВЛЕНИЕ: Это относится только к приложениям QtWidget. Для QtQuick/QML все еще много мерцания, начиная с Qt 6.3. См., например. https://bugreports.qt.io/browse/QTBUG-103201

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