New to QT, and suspect I have a case where I am breaking some rule, or using a bad approach. I realize code would be best, but I have not found a good way to reduce this to a complete, postable example, so with apologies in advance I will try to provide enough code snippets to explain.
First, let me show you the result. Please see two screen shots attached, one that worked, one that has the failure. They are a display of sheet music, with a momentary overlay showing areas of the screen in color. As you can see, one shows a badly distorted image. At times it is much more distorted than you see here, where the colored areas are not even clearly distinguished.
The only difference in these two is a delay in creating the overlay (the delay lets it work).
The Underlying screen structure, before the overlay, looks like this (nesting shown by indents, abbreviated):
This resides in a QMainWindow class, and outerLayoutWidget is set as the central widget. The various widgets are hidden and visible as needed, and seem to work fine as activity occurs.Qt Code:
QVBoxLayout* outerLayout; QWidget* menuLayoutWidget; QHBoxLayout* menuLayout; QWidget* mainMenuLayoutWidget; QHBoxLayout* mainMenuLayout; QPushButton* libraryButton; ... QWidget* playerMenuLayoutWidget; QHBoxLayout* playerMenuLayout; QPushButton* playButton; QPushButton* firstButton; ....To copy to clipboard, switch view to plain text mode
At one point I want to overlay the entire screen (i.e. mainwindow) with a painted overlay for a few seconds. This occurs in code (as action from a button press) which creates quite a few new widgets inside of outerLayout (and with outerLayoutWidget as parent), and then I do this (the variable overlay is defined in the mainwindow class header to match the TipOverlay class).
Qt Code:
overlay = new TipOverlay(outerLayoutWidget); overlay->show();To copy to clipboard, switch view to plain text mode
TipOverlay.h (irrelevant stuff edited):
Qt Code:
{ Q_OBJECT private: public: ~TipOverlay(); };To copy to clipboard, switch view to plain text mode
and in that routine I do a lot of painting into a pixmap and display it (again, simplified a bit)
Qt Code:
{ assert(parent); p = parent; this->setGeometry((p->geometry())); painter.setOpacity(0.4); // For panels .... lots of painting and text code this->setPixmap(tmpPix); this->show(); [=] { ... nothing here now, eventually animation change } ); [=] { ... nothing here now, eventually animation change this->deleteLater(); } ); }To copy to clipboard, switch view to plain text mode
I originally had animation in this to fade in and out which I thought may be the problem but have stripped it out. The timers right now only call the deleteLater() to remove it.
As shown above, it almost always gives the distorted view. On a subsequent iteration of the code, however, it works (due to buffering of the images a subsequent iteration takes less computation to produce the underlying screen). Because of this I introduced a half second delay before calling the "new TipOverlay" -- works every time.
Just to be clear, just before the overlay is created (and without releasing control back to the event processor) the underlying screen has been changed - widgets hidden, background color changed, images resized and overlay is the last thing before releasing control.
Incidentally, when the timer runs and the overlay deletes itself, the underlying screen is always displayed correctly, i.e. the distortion is not actually a corruption of the rest of the screen.
Also, if I set opacity to 1 in the overlay, that part painted works fine -- it is the partially-see-through portions that are at issue.
This leads me to think I am doing something wrong in creating and displaying the overlay widget, perhaps I need to do it in a separate event.
I HAVE read the information on using QPainter only in a paint event, but I frankly cannot see how to do that, especially once I start using animation. Trying it in the event handler made it hang in what appeared to be a loop, I assume animation changes calling it recursively? I also have read that painting into a QPixmap object that is separately set is an exception to that rule (is it?).
Some specific questions:
- Am I right that painting into, and putting a pixmap in a Qlabel outside of a paint event is OK?
- I am putting this overlay widget as a child of the outermost widget (inside the mainwindow), but am not putting it in the QVBoxLayout that other widgets are in (as I am forcing its layout with the geometry copy). Is that correct?
- Is there anything wrong with a class inheriting from QLabel producing its own image with QPainter as I have done?
- Noting that if painted at opacity 1, the overlay looks fine (at least the the parts painted), it is the areas transparent (unpainted) or partially transparent (painted at opacity 0.4) that are distorted -- is that supposed to work? To see-through to a just-changed widget(s) underneath? Do I need to wait in some fashion for that to be rendered before overlaying it? (If so, how to detect it is ready, as I don't want to guess with a time frame).
I realize this is long (even without complete code) and thank anyone who just got to the bottom, but especially if you might give me a pointer where to look.
Bookmarks