Hello,
Here is the problem. A Widget takes time to render (this is the short explanation) and upon a paintEvent we want to render it in two stages:
1/ If not already done, render the Widget into a cache (Pixmap)
2/ Do the actual painting of the Widget using the cache.
I tried the naive solution below:
template <class WIDGET>
class CachedWidget : public WIDGET
{
public:
CachedWidget
(QWidget *parent
= 0) : WIDGET
(parent
), m_paintState
(Idle
) { }
switch(m_paintState) {
case Idle: // paint event occurred when widget was 'idle'
m_paintState = Painting;
if(m_cache.
size() != QWidget::size()) { }
// this will somehow trigger a secondary paint event
// this is out of our control
painter.drawPixmap(event->rect(), m_cache, event->rect()); }
m_paintState = Idle;
break;
case Painting: // paint event occurred when widget was already painting
WIDGET::paintEvent(event);
break;
}
}
private:
enum PaintState { Idle, Painting };
PaintState m_paintState;
};
int main(int argc, char *argv[])
{
CachedWidget<QWidget> w;
w.show();
return a.exec();
}
template <class WIDGET>
class CachedWidget : public WIDGET
{
public:
CachedWidget(QWidget *parent = 0) : WIDGET(parent), m_paintState(Idle) { }
virtual void paintEvent ( QPaintEvent * event ) {
switch(m_paintState) {
case Idle: // paint event occurred when widget was 'idle'
m_paintState = Painting;
if(m_cache.size() != QWidget::size()) {
m_cache = QPixmap(QWidget::size());
}
// this will somehow trigger a secondary paint event
// this is out of our control
QWidget::render(&m_cache);
{ QPainter painter(this);
painter.drawPixmap(event->rect(), m_cache, event->rect()); }
m_paintState = Idle;
break;
case Painting: // paint event occurred when widget was already painting
WIDGET::paintEvent(event);
break;
}
}
private:
enum PaintState { Idle, Painting };
PaintState m_paintState;
QPixmap m_cache;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CachedWidget<QWidget> w;
w.show();
return a.exec();
}
To copy to clipboard, switch view to plain text mode
This 'solution' does not work because to render the Widget into a cache we have to resort to the QWidget::render() function, and this function happens to somehow trigger another paintEvent, and Qt forbids reentrancy in the paintEvent() method.
The question is the following. When inside the paintEvent() function, is there a way to perform the painting into a QPaintDevice that is different than the Widget that received the QPaintEvent?
Or is it possible to otherwise implement a caching system similar to the the intention above?
Another question: since the render() method manages to render a QWidget in a different QPaintDevice, why does it have to send a QPaintEvent to the QWidget?
Thanks!
Bookmarks