PDA

View Full Version : QMainWindow or QDialog show() - before displaying, the window area is painted white



VVS
14th October 2020, 08:36
QMainWindow or QDialog show() - before displaying, the window area is painted white. You may not notice this on fast computers. How to avoid this ?

auto*w=new Dialog1();
w->show();
If I use

auto*w=new Dialog1();
w->setWindowFlags(Qt::FramelessWindowHint);
w->show();
then there is no white paint, but there is no window header


Windows 10. Desktop Qt 5.15.0 MinGW 64-bit

Link to project https://drive.google.com/file/d/1vpuon7lIByZzgjJ0nBg8qU1e5SZAX46Z/view

Link to Video - https://drive.google.com/file/d/1-gs5UrD62f_JIUFYu4zZftSaxCAbV9zr/view?usp=sharing

d_stranz
14th October 2020, 18:29
The paint handling clears the window contents and fills it with the background color before calling the actual paintEvent() for the widget. If you don't want this, then set the QWidget::autoFillBackground() property to false when you construct the widget. This means that if there is anything already drawn in the window, it won't be erased and new drawing will happen on top of it. If nothing has changed since the last repaint, this will be fine, but if there have been changes then either you clear the background yourself to start with a clean background or you get an overlaid mess.

I don't know why you think setting a FramelessWindowHint would have anything to do with clearing the background.

But if what you -really- want is a window with a transparent background, then you need to call QWidget::setAttribute() with Qt::WA_TranslucentBackground set to true alnog with Qt::WA_FramelessWindowHint. If you don't want a frameless window, then you could alternatively call QWidget::setWindowOpacity() with a value of 0.

VVS
15th October 2020, 08:58
1.
I don't know why you think setting a FramelessWindowHint would have anything to do with clearing the background
I just showed an example where there is no problem

2.
The paint handling clears the window contents and fills it with the background color before calling the actual paintEvent() for the widget. If you don't want this, then set the QWidget::autoFillBackground() property to false when you construct the widget

auto*w=new Dialog1();
w->setAutoFillBackground(false);
w->show();
This doesn't solve the problem

d_stranz
15th October 2020, 18:10
I just showed an example where there is no problem

And you complained because the window was frameless.


This doesn't solve the problem

Have you read the documentation for QWidget::setAutoFillBackground()? There may be other requirements in order for this flag to have any effect.

VVS
16th October 2020, 07:58
Have you read the documentation for QWidget::setAutoFillBackground()? There may be other requirements in order for this flag to have any effect.

Thank you for the link. But it didn't help me. Can you provide a working code ?

d_stranz
16th October 2020, 15:52
Can you provide a working code ?

Sorry, no. I have never considered clearing a window before painting to be a problem and have never written code to try to work around that. I don't have any time to investigate it. Maybe someone else who follows this forum will have a solution or another suggestion.

ChrisW67
17th October 2020, 06:19
Not sure why a eye-bleeding red background is desirable, but tastes vary.

The doc for QWidget::setAutoFillBackground (https://doc.qt.io/qt-5/qwidget.html#autoFillBackground-prop) carries this warning that applies directly to your situation:

Warning: Use this property with caution in conjunction with Qt Style Sheets. When a widget has a style sheet with a valid background or a border-image, this property is automatically disabled.
So, this property was already disabled.

Those docs also provide this:

In addition, Windows are always filled with QPalette::Window, unless the WA_OpaquePaintEvent or WA_NoSystemBackground attributes are set.
You could try setAttribute(Qt::WA_OpaquePaintEvent, true) in your dialog constructor. I do not have your platform to test one: it is not quite right on mine.

Depending on exactly what you are trying to achieve: remove the style sheet from Dialog1.ui and modify the palette in Designer so that QPalette::Window is Red.

VVS
17th October 2020, 16:39
Not sure why a eye-bleeding red background is desirable, but tastes vary
The word "red" is shorter than others. Any colors are allowed in the training project


remove the style sheet from Dialog1.ui and modify the palette in Designer so that QPalette::Window is Red.
I removed the style sheet from Dialog1.ui


You could try setAttribute(Qt::WA_OpaquePaintEvent, true) in your dialog constructor

Dialog1::Dialog1(QWidget *parent) :
QDialog(parent),ui(new Ui::Dialog1)
{
ui->setupUi(this);

QDialog::setAttribute(Qt::WA_OpaquePaintEvent,true );

QPalette pal = palette();
pal.setColor(QPalette::Background, Qt::red);
setPalette(pal);
}
The result is in the video. The code is visible also there https://drive.google.com/file/d/1d3_ejLoENKHYvPagOM0ZOXOmv0Zq-efK/view?usp=sharing

if

setAttribute(Qt::WA_OpaquePaintEvent, false)
the window is painted red

It's not just my problem - https://forum.qt.io/topic/68655/turning-off-background-fill-on-qdialog

ChrisW67
18th October 2020, 06:17
Compare what I wrote:

remove the style sheet from Dialog1.ui and modify the palette in Designer so that QPalette::Window is Red.
to what you did in your code:


QPalette pal = palette();
pal.setColor(QPalette::Background, Qt::red);


You can actually make that palette adjustment to QPalette::Window in Designer if you wish. The QPalette::Window comes from the docs linked earlier.

The other thing I did in your project was apply a layout to everything in your Dialog1. I do not think this will make a difference to the painting only the layout and usability.

VVS
18th October 2020, 14:07
You can actually make that palette adjustment to QPalette::Window in Designer
I changed the color of the palette-Window and others in the designer. But it didn't help

VVS
27th October 2020, 11:32
I solved this problem.


class Dialog1 : public QDialog
{
Q_OBJECT

public:
explicit Dialog1(QWidget *parent = nullptr);
~Dialog1();

private:
Ui::Dialog1 *ui;
protected:
bool event(QEvent*e);
};

Dialog1::Dialog1(QWidget *parent) :
QDialog(parent),ui(new Ui::Dialog1)
{
ui->setupUi(this);

setWindowFlags(Qt::Window);
setWindowOpacity(0);
}

bool Dialog1::event(QEvent*e)
{
if(e->type()==QEvent::WindowActivate)
{
QTimer::singleShot(0,NULL,[this](){this->setWindowOpacity(1);});
return true;
}
if(e->type()==QEvent::Hide)
{
setWindowOpacity(0);
return true;
}
return QDialog::event(e);
}

This is not a Qt problem, this is a Windows problem. I looked at my WPF and Windows Forms projects and saw that they have this problem. You can also see it by running Windows Explorer or Windows Task Manager. Another question is whether this is considered a problem. I think so, Yes. This flickering hits my eyes