Qt-interest Archive, September 2002
double buffering when subclassing widgets
Message 1 in thread
Hi there!
I'm relatively new with QT, but have read all of the documentation that
I could get my hands on, including the list archives.
My problem is this:
I've subclassed QSlider to create a new slider with some additional
'stuff' on the top of it. (Limits, a marker for a default position,
etc.)
The problem is that it flickered enough to induce seizure, especially
when the data driving the sliders was from a live A/D capture card and
they were on the move a lot.
One solution which presented itself from the archives of this list was
to use QPainter::redirect(this, buffer_pixmap); to make the QSlider draw
it's goodness into a buffer, draw my additional goodness on top of it,
and THEN bitBlt the entire thing onto the screen.
I tried to do this, but have been wildly unsuccessful.
What I did:
-----------------
* set up the buffer (buffer_pixmap) in the constructor
* did the QPainter::redirect (this, &buffer_pixmap) call in the
constructor
* re-implemented paintEvent(QPaintEvent *e)
(stripped down version:)
//this takes care of the case in which we've resized between now & the
last drawing attempt
if(buffer_pixmap.width() != geometry().width() || buffer_pixmap.height()
!= geometry().height())
buffer_pixmap.resize(geometry().width(), geometry().height());
QSlider::paintEvent(e);
bitBlt(this, 0, 0, &buffer_pixmap);
-----------------
The result is a chaotic mess; odd blue backgrounds, flickering way worse
than before, etc. etc. etc.
Any suggestions?
Thanks...
Josh
Message 2 in thread
Okay then! I've solved my own problem, so for the sake of posterity (and
for the sake of critique) I'm posting it here.
The main trick was clearing out the pixmap before writing; apparently
(and this makes sense) when the widgets draw, they expect some kind of
sane background to already be there.
buffer_pixmap.fill(this);
(using the 'this' pointer pulls the background color from the widget.)
And in the interest of speed, trick #2 comes into play: only draw what
needs to be drawn as passed to us by the QPaintEvent.
The previous line becomes:
buffer_pixmap.fill(this, e->rect().topLeft());
Correspondingly, when it comes time to actually write the mess to
screen, calling bitBlt with the 'only draw in certain regions' option
makes a big difference.
bitBlt(this, e->rect().topLeft(), &buffer_pixmap, e->rect());
The -other- major flicker-causing issue was that after needing to
reposition my custom decorations to qSlider, I'd been calling
this->repaint(), because it seemed to be the only way to flush the
background and get rid of the 'ghosts of widgets past'. Crafting my own
QPaintEvent with the proper bounding rectangle and calling
paintEvent(mypaintevent)
instead of
repaint()
did wonders for reducing flicker.
Hope that helps someone . . . if I appear to be certifiably out to
lunch, please don't hesitate to say so.
Josh