From 82b71e49603bf3a53240076c395864addd869267 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 18 Feb 2013 20:35:59 -0600 Subject: [PATCH] Doublebuffer QIconView to reduce flicker This closes Bug 1408 --- src/iconview/qiconview.cpp | 47 +++++++++++++++++++++++++++++++++++++- src/iconview/qiconview.h | 1 + 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/iconview/qiconview.cpp b/src/iconview/qiconview.cpp index 66fa498..9fd3022 100644 --- a/src/iconview/qiconview.cpp +++ b/src/iconview/qiconview.cpp @@ -214,6 +214,7 @@ public: QIconViewItem *currentItem, *tmpCurrentItem, *highlightedItem, *startDragItem, *pressedItem, *selectAnchor, *renamingItem; QRect *rubber; + QPixmap *backBuffer; QTimer *scrollTimer, *adjustTimer, *updateTimer, *inputTimer, *fullRedrawTimer; int rastX, rastY, spacing; @@ -2800,6 +2801,7 @@ QIconView::QIconView( QWidget *parent, const char *name, WFlags f ) d->currentItem = 0; d->highlightedItem = 0; d->rubber = 0; + d->backBuffer = 0; d->scrollTimer = 0; d->startDragItem = 0; d->tmpCurrentItem = 0; @@ -2953,6 +2955,8 @@ QIconView::~QIconView() delete item; item = tmp; } + delete d->backBuffer; + d->backBuffer = 0; delete d->fm; d->fm = 0; #ifndef QT_NO_TOOLTIP @@ -4972,6 +4976,47 @@ void QIconView::contentsDropEvent( QDropEvent *e ) } #endif +/*! + This function grabs all paintevents that otherwise would have been + processed by the QScrollView::viewportPaintEvent(). Here we use a + doublebuffer to reduce 'on-paint' flickering on QIconView + (and of course its children). + + \sa QScrollView::viewportPaintEvent(), QIconView::drawContents() +*/ + +void QIconView::bufferedPaintEvent( QPaintEvent* pe ) +{ + QWidget* vp = viewport(); + QRect r = pe->rect() & vp->rect(); + int ex = r.x() + contentsX(); + int ey = r.y() + contentsY(); + int ew = r.width(); + int eh = r.height(); + + if ( !d->backBuffer ) + d->backBuffer = new QPixmap(vp->size()); + if ( d->backBuffer->size() != vp->size() ) { + // Resize function (with hysteresis). Uses a good compromise between memory + // consumption and speed (number) of resizes. + float newWidth = (float)vp->width(); + float newHeight = (float)vp->height(); + if ( newWidth > d->backBuffer->width() || newHeight > d->backBuffer->height() ) + { + newWidth *= 1.1892; + newHeight *= 1.1892; + d->backBuffer->resize( (int)newWidth, (int)newHeight ); + } else if ( 1.5*newWidth < d->backBuffer->width() || 1.5*newHeight < d->backBuffer->height() ) + d->backBuffer->resize( (int)newWidth, (int)newHeight ); + } + + QPainter p; + p.begin(d->backBuffer, vp); + drawContentsOffset(&p, contentsX(), contentsY(), ex, ey, ew, eh); + p.end(); + bitBlt(vp, r.x(), r.y(), d->backBuffer, r.x(), r.y(), ew, eh); +} + /*! \reimp */ @@ -5756,7 +5801,7 @@ bool QIconView::eventFilter( QObject * o, QEvent * e ) if ( !d->rubber ) drawDragShapes( d->oldDragPos ); } - viewportPaintEvent( (QPaintEvent*)e ); + bufferedPaintEvent( (QPaintEvent*)e ); if ( d->dragging ) { if ( !d->rubber ) drawDragShapes( d->oldDragPos ); diff --git a/src/iconview/qiconview.h b/src/iconview/qiconview.h index 97780d8..109779f 100644 --- a/src/iconview/qiconview.h +++ b/src/iconview/qiconview.h @@ -452,6 +452,7 @@ protected: void contentsDropEvent( QDropEvent *e ); #endif + void bufferedPaintEvent( QPaintEvent* ); void resizeEvent( QResizeEvent* e ); void keyPressEvent( QKeyEvent *e ); void focusInEvent( QFocusEvent *e );