Я наблюдаю странное поведение при изменении размера QWindow
. Когда я изменяю размер окна так, что ширина и высота увеличиваются или уменьшаются, окно не мерцает белым фоном. Но когда я увеличиваю ширину при уменьшении высоты (или наоборот), окно мерцает и временно заполняет новые области белым цветом. Это очень раздражающий эффект, особенно когда у меня в приложении темная тема и я изменяю размер окна.
Чтобы поэкспериментировать с этим, я использовал пример «растрового окна», входящий в состав Qt SDK. Здесь не используется QtWidgets
, поэтому я использовал этот пример, чтобы исключить эффект, вызванный виджетами. Я добавил функцию QThread::msleep(100);
к RasterWindow::render(QPainter *)
, чтобы имитировать очень медленный рендеринг. Затем я попытался изменить размер окна. Я могу наблюдать это только в Windows, но не в Linux или Mac. Смотрите прикрепленный GIF.
Мои вопросы:
ОБНОВЛЕНИЕ: здесь я создал минималистичный пример
/*
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. Я пробовал многие не-Qt приложения для Windows, такие как File Explorer, Total Commander, Foobar2000, Notepad++. Ни у кого из них нет такого мерцания. Отсюда я делаю вывод, что это не проблема Windows. Кажется, это проблема Qt, потому что только приложения Qt демонстрируют такое уродливое поведение.
@G.M. Я полностью понимаю ваше объяснение, но оно не объясняет, почему оно мерцает только тогда, когда одно измерение увеличивается, а другое уменьшается. И почему он НЕ мерцает, когда оба измерения увеличиваются.
Я вижу такое поведение во всех окнах Windows 10 (Проводник, Chrome, Настройки и т. д.). Я думал, что это просто Qt, но это похоже на ошибку Windows 10. Медленно изменяя размер, я могу даже получить постоянные сбои, которые остаются возле краев ветра, пока вы не щелкнете строку заголовка.
есть еще несколько случаев, когда вы получите мерцание, см. ошибку bugreports.qt.io/browse/QTBUG-98122. Решение, которое мы нашли, состоит в том, чтобы явно установить GCLP_HBRBACKGROUND на нулевую кисть, чтобы при изменении размера окна цвет заливки не был белым.
Эта ошибка была исправлена в Qt 6.1. Насколько я проверял, в моих проектах мерцание белых областей исчезло.
ОБНОВЛЕНИЕ: Это относится только к приложениям QtWidget. Для QtQuick/QML все еще много мерцания, начиная с Qt 6.3. См., например. https://bugreports.qt.io/browse/QTBUG-103201
Эффект, который вы видите, довольно часто зависит от базовой графической/оконной системы. Когда размер окна изменяется, оно заполняет это окно цветом фона и рисует кэшированное предыдущее содержимое, закрепленное в одном углу (обычно в верхнем левом).