QProgressBar has rendering errors or does not render at all
-
Why does this progress bar always have rendering errors or fail to render at all? Unless the content of the
textis not updated or the graphical effects of thetextare removed.The code is like this:
#include <QGraphicsDropShadowEffect> #include <QProgressBar> #include <QApplication> #include <QVBoxLayout> #include <QDateTime> #include <QLabel> class Test : public QWidget { QProgressBar pb; QLabel text; QVBoxLayout layout{this}; public: Test(): pb(this), text(this) { layout.addWidget(&text, 0, Qt::AlignCenter); layout.addWidget(&pb); pb.setMaximum(3600); /* Setting it to 50ms is just to see the anomaly more quickly. Changing it to 500ms can still reproduce the issue. */ startTimer(50); auto g = new QGraphicsDropShadowEffect; g->setBlurRadius(10);// It affects both heoccurence and severity of this condition. g->setOffset(0, 0); g->setColor(Qt::white); text.setGraphicsEffect(g); text.setStyleSheet( "font-size: 24px;" "font-weight: bold;" "color: rgb(66, 66, 66);" ); pb.setTextVisible(false); } void timerEvent(QTimerEvent* event) override { if (QDateTime::currentMSecsSinceEpoch() % 2) pb.setValue(pb.value() + 1);//If the number 1 is changed to a number greater than or equal to 20, it will work normally static int counter = 1; text.setText(QString::number(counter++)); } }; int main(int argc, char** argv) { QApplication app(argc,argv); Test t; t.show(); return app.exec(); }I think it’s because some unknown reason caused the content drawn by the
repaintcalled in thesetValueofQProgressBarto be lost (as if it was never drawn at all). The upper part of thepbprogress bar was correctly drawn because thetextused a graphical effect, which increased the drawing range and thus drew that part of thepbprogress bar.The result of the execution is like this:

I'm certain that the
paintEventofpbhas been executed, because I tried writing a class to test it, and the result is that it indeed has been executed and continues to be executed constantly.class ProgressBar : public QProgressBar { public: ProgressBar(QWidget* parent = nullptr): QProgressBar(parent) {} void paintEvent(QPaintEvent* event) { static int counter = 1; QProgressBar::paintEvent(event); qDebug() << "paintEvent(QPaintEvent*)" << counter++; } };The code has been tested on Linux with Qt 6.9.0 and 6.5.5, as well as on Windows with Qt 6.9.0. The results were either rendering errors or no rendering at all.
-
Why does this progress bar always have rendering errors or fail to render at all? Unless the content of the
textis not updated or the graphical effects of thetextare removed.The code is like this:
#include <QGraphicsDropShadowEffect> #include <QProgressBar> #include <QApplication> #include <QVBoxLayout> #include <QDateTime> #include <QLabel> class Test : public QWidget { QProgressBar pb; QLabel text; QVBoxLayout layout{this}; public: Test(): pb(this), text(this) { layout.addWidget(&text, 0, Qt::AlignCenter); layout.addWidget(&pb); pb.setMaximum(3600); /* Setting it to 50ms is just to see the anomaly more quickly. Changing it to 500ms can still reproduce the issue. */ startTimer(50); auto g = new QGraphicsDropShadowEffect; g->setBlurRadius(10);// It affects both heoccurence and severity of this condition. g->setOffset(0, 0); g->setColor(Qt::white); text.setGraphicsEffect(g); text.setStyleSheet( "font-size: 24px;" "font-weight: bold;" "color: rgb(66, 66, 66);" ); pb.setTextVisible(false); } void timerEvent(QTimerEvent* event) override { if (QDateTime::currentMSecsSinceEpoch() % 2) pb.setValue(pb.value() + 1);//If the number 1 is changed to a number greater than or equal to 20, it will work normally static int counter = 1; text.setText(QString::number(counter++)); } }; int main(int argc, char** argv) { QApplication app(argc,argv); Test t; t.show(); return app.exec(); }I think it’s because some unknown reason caused the content drawn by the
repaintcalled in thesetValueofQProgressBarto be lost (as if it was never drawn at all). The upper part of thepbprogress bar was correctly drawn because thetextused a graphical effect, which increased the drawing range and thus drew that part of thepbprogress bar.The result of the execution is like this:

I'm certain that the
paintEventofpbhas been executed, because I tried writing a class to test it, and the result is that it indeed has been executed and continues to be executed constantly.class ProgressBar : public QProgressBar { public: ProgressBar(QWidget* parent = nullptr): QProgressBar(parent) {} void paintEvent(QPaintEvent* event) { static int counter = 1; QProgressBar::paintEvent(event); qDebug() << "paintEvent(QPaintEvent*)" << counter++; } };The code has been tested on Linux with Qt 6.9.0 and 6.5.5, as well as on Windows with Qt 6.9.0. The results were either rendering errors or no rendering at all.
@YuXin said in QProgressBar has rendering errors or does not render at all:
if (QDateTime::currentMSecsSinceEpoch() % 2) pb.setValue(pb.value() + 1);This is probably quite irrelevant to whatever your issue is. But as a "reproducer" I don't understand: you have no idea whether the
ifwill be true always/never/somewhere in between. Or will vary from run to run. If it's always false it will never be hit. It might work for you in practice but not for someone else. -
@YuXin said in QProgressBar has rendering errors or does not render at all:
if (QDateTime::currentMSecsSinceEpoch() % 2) pb.setValue(pb.value() + 1);This is probably quite irrelevant to whatever your issue is. But as a "reproducer" I don't understand: you have no idea whether the
ifwill be true always/never/somewhere in between. Or will vary from run to run. If it's always false it will never be hit. It might work for you in practice but not for someone else. -
@JonB This was actually reflected in the testing of the paintEvent calls, but I'm not sure why hard-coding the condition in this if statement would prevent it from being reproduced.
@YuXin
You have no idea/guarantee what numberQDateTime::currentMSecsSinceEpoch()will return each time (and hence whether it will be odd or even always/never/sometimes), you cannot rely on that even matching aQTimerevent in real time. [With your choice ofstartTimer(50);it's likely to be either always true or always false, I would have thought. At leaststartTimer(49)would more likely alternate.] Just saying, leave it at that. -
@YuXin
You have no idea/guarantee what numberQDateTime::currentMSecsSinceEpoch()will return each time (and hence whether it will be odd or even always/never/sometimes), you cannot rely on that even matching aQTimerevent in real time. [With your choice ofstartTimer(50);it's likely to be either always true or always false, I would have thought. At leaststartTimer(49)would more likely alternate.] Just saying, leave it at that.@JonB The timing of the
startTimerdoes not affect the issue. Regardless of how it is adjusted, the problem can still be reproduced. Even if it is increased tenfold to 500, the issue persists—it's just that a shorter interval allows the problem to occur more quickly.Additionally, the purpose of this if statement is exactly as you assumed: to randomly trigger
setValue, rather than being aligned with the 50-interval setting. -
@JonB The timing of the
startTimerdoes not affect the issue. Regardless of how it is adjusted, the problem can still be reproduced. Even if it is increased tenfold to 500, the issue persists—it's just that a shorter interval allows the problem to occur more quickly.Additionally, the purpose of this if statement is exactly as you assumed: to randomly trigger
setValue, rather than being aligned with the 50-interval setting.@YuXin said in QProgressBar has rendering errors or does not render at all:
The timing of the startTimer does not affect the issue.
In principle an odd number is more likely to trigger
QDateTime::currentMSecsSinceEpoch() % 2being true on alternates than always being either true or false.the purpose of this if statement is exactly as you assumed: to randomly trigger setValue
Exactly. And for that you would be much better off using a random number than your potentially-deterministic
QDateTime::currentMSecsSinceEpoch() % 2.Anyway, I am sorry if we digressed. I intended this to be a brief comment, especially for posting for others to reproduce.
-
Hi,
Which version of Qt are you using ?
On which OS ? -
@YuXin Sorry, I missed that line.
Could you test with a more recent version of Qt ?
One small note: you are using a pretty large range which means that you won't necessarily see the painting done immediately. While it's likely unrelated to the issue at hand, it adds an unnecessary delay to test your issue.
-
@YuXin Sorry, I missed that line.
Could you test with a more recent version of Qt ?
One small note: you are using a pretty large range which means that you won't necessarily see the painting done immediately. While it's likely unrelated to the issue at hand, it adds an unnecessary delay to test your issue.
-
Hi, it seems you have a race condition, i.e. the graphics effect and the progress bar are fighting each other, and currently the graphics effect is winning.
Try giving the progress bar the upper hand by telling it to repaint, say like this:
... // add a repaint call void timerEvent(QTimerEvent* event) override { if (QDateTime::currentMSecsSinceEpoch() % 2) { pb.setValue(pb.value() + 1);//If the number 1 is changed to a number greater than or equal to 20, it will work normally pb.repaint(); } static int counter = 1; text.setText(QString::number(counter++)); } ... -
@SGaist The fact that the same issue occurred during the testing of version 6.9.0 clearly indicates that upgrading the version is useless. I also tested the currently latest version, 6.10, and the result is that the same problem persists.
@YuXin said in QProgressBar has rendering errors or does not render at all:
@SGaist The fact that the same issue occurred during the testing of version 6.9.0 clearly indicates that upgrading the version is useless. I also tested the currently latest version, 6.10, and the result is that the same problem persists.
No, it only indicates that there's an issue with the version you tested against.
Since it still happens with 6.10, then there's indeed something to investigate.
Try the suggestion of @hskoglund and if does not improve the situation, then check the bug report system and if you don't find anything there, please open a new ticket providing your minimal example with the adjustments people suggested on this thread.
-
@YuXin said in QProgressBar has rendering errors or does not render at all:
@SGaist The fact that the same issue occurred during the testing of version 6.9.0 clearly indicates that upgrading the version is useless. I also tested the currently latest version, 6.10, and the result is that the same problem persists.
No, it only indicates that there's an issue with the version you tested against.
Since it still happens with 6.10, then there's indeed something to investigate.
Try the suggestion of @hskoglund and if does not improve the situation, then check the bug report system and if you don't find anything there, please open a new ticket providing your minimal example with the adjustments people suggested on this thread.
-
Hi, it seems you have a race condition, i.e. the graphics effect and the progress bar are fighting each other, and currently the graphics effect is winning.
Try giving the progress bar the upper hand by telling it to repaint, say like this:
... // add a repaint call void timerEvent(QTimerEvent* event) override { if (QDateTime::currentMSecsSinceEpoch() % 2) { pb.setValue(pb.value() + 1);//If the number 1 is changed to a number greater than or equal to 20, it will work normally pb.repaint(); } static int counter = 1; text.setText(QString::number(counter++)); } ...@hskoglund First of all, I sincerely apologize for the delayed reply—I’ve been extremely busy.
Secondly, your proposal is indeed feasible, but I’d like to know what you mean by "race condition"—I’ve never heard of it before.
Is there any documentation that explains this?
-
@hskoglund First of all, I sincerely apologize for the delayed reply—I’ve been extremely busy.
Secondly, your proposal is indeed feasible, but I’d like to know what you mean by "race condition"—I’ve never heard of it before.
Is there any documentation that explains this?
-
Hi, it seems you have a race condition, i.e. the graphics effect and the progress bar are fighting each other, and currently the graphics effect is winning.
Try giving the progress bar the upper hand by telling it to repaint, say like this:
... // add a repaint call void timerEvent(QTimerEvent* event) override { if (QDateTime::currentMSecsSinceEpoch() % 2) { pb.setValue(pb.value() + 1);//If the number 1 is changed to a number greater than or equal to 20, it will work normally pb.repaint(); } static int counter = 1; text.setText(QString::number(counter++)); } ...@hskoglund I looked into it: when changing the progress bar value, it internally calls
repaint, which should trigger an immediate redraw.On the other hand, the label uses
update, but the call to
updateshouldn’t be executed until the
repaintis completed. Moreover, by the time this timer event starts, the previous drawing of the label should already have been completed.Why would there be a race condition in this scenario?
-
There is no race condition but you use QGraphicsDropShadowEffect for a child widget with a radius of 10 so this widget is responsible for drawing everything of it's size + 10 pixel which overlaps with your progressbar.
I don't understand why you use QGraphicsDropShadowEffect with this large radius at all. What do you want to achieve for a plain QWidget not in a QGraphicsScene? -
There is no race condition but you use QGraphicsDropShadowEffect for a child widget with a radius of 10 so this widget is responsible for drawing everything of it's size + 10 pixel which overlaps with your progressbar.
I don't understand why you use QGraphicsDropShadowEffect with this large radius at all. What do you want to achieve for a plain QWidget not in a QGraphicsScene?@Christian-Ehrlicher I also think there is no race condition here, but can you tell me why their overlapping drawing areas would cause this? I'm really curious about the reason, even though I already know the solution.
-
As I said - the effect draws outside it's client area.