PDA

View Full Version : QGraphicsEffect for nested groups



japcrword
15th January 2015, 12:16
I'm using QGraphicsScene and I need to draw item groups having effects. I've found a bug in the application and could reproduce it in a small test application.
There are 2 conditions that I cannot avoid:
A) drawing also occurs in a background thread with QGraphicsScene::render (hence no QPixmap's should be used);
B) in order to draw the effect I need to use a (3rd party) complex implementation that works on QImage.
The only solution seemed to be simply using QGraphicsEffect::drawSource with QPainter drawing on a QImage then drawing that QImage with the original QPainter (passed to QGraphicsEffect::draw):


void BorderEffect::drawImpl(QPainter *p, DrawMethod meth) {
...
// ================================================== =================
// The main question is how can I get the same result
// as with previous 2 methods (Call_QtDrawSource, Draw_QtSourcePixmap)
// when using a temporary QImage buffer for drawSource?
// Is it possible to solve it with setting transformations to pxpainter and p?
const QRectF br = boundingRectFor(sourceBoundingRect());

QImage px(br.width(), br.height(), QImage::Format_ARGB32_Premultiplied);
px.fill(Qt::transparent);
{
QPainter pxpainter(&px);
pxpainter.setTransform(QTransform::fromTranslate(-br.left(), -br.top()));
drawSource(&pxpainter);
}
px = apply_3rd_party_effect_to(px);
p->drawImage(br.left(), br.top(), px);
...

The problem is I cannot achieve the same effect as with QGraphicsEffect::drawSource or when drawing QGraphicsEffect::sourcePixmap. I attached the whole sample code of the test application (graphiceffect_test_01.zip), there are 3 menu items which correspond to drawSource, sourcePixmap and drawing on intermediate QImage. You can see the difference when resizing the window or dragging the green rectangle item (the first 2 methods/menu-items produce correct effect and the third does not).
Ideally I need to create a QImage which looks like QGraphicsEffect::sourcePixmap, but since this code might be invoked from a background thread (condition A) I need to reimplement QGraphicsEffect::drawSource which uses internal Qt methods that I cannot access.
To me it looks like a Qt bug, but I would like to hear a confirming opining. I believe that passing QPainter different from that in QGraphicsEffect::draw to QGraphicsEffect::drawSource is legal, since it's not forbidden by the docs, it produces no qWarnings and it's handled by special if in void QGraphicsItemEffectSourcePrivate::draw (see qgraphicsitem.cpp). So my questions are:
- May it be really considered a Qt bug or am I missing something?
- Is there a reasonably easy workaround satisfying conditions A and B?
Thanks.

japcrword
16th January 2015, 08:50
So to put it plainly. I need a way to draw the same as QGraphicsEffect::sourcePixmap only as a QImage but without using QPixmap class (i.e. QGraphicsEffect::sourcePixmap().toImage() is no solution). If it's possible then how? If it's not possible with drawSource then this should probably be considered a bug, should it not?