3

I'm developing a new QML element in C++ based on this sample code. My class inherits from QDeclarativeItem and it's paint() method is responsible to draw a QImage to the screen:

void NewQMLitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    // image is QImage* that was loaded at the constructor of the class
    painter->drawImage(0, 0, *image);
}

The widget size is 800x480 and the image is 400x240. The code below works perfectly as long as the drawing starts at (0, 0), as you can see below:

The problem I'm facing is that drawing at an arbitrary coordinate such as(200, 0), seems to clip the drawing. It looks like QPainter only updates the screen starting from (0, 0):

void NewQMLitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawImage(200, 0, *image);
}

And the following is the result:

My current workaround involves calling widget->update() at the end of the paint(). Of course, this is terrible because it makes the widget be painted twice.

What is the proper way to handle this? I'm currently using Qt 5.2 on Windows.

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • It looks like different images. The gray diagonal stripes on the left of the second image aren't there in the first image. And so the black part that you think is "clipped" might also just be a difference between the images? – Cheers and hth. - Alf May 19 '14 at 01:23
  • True! The images above where taken during a live capture from a webcam. My application is not loading static images from the disk. Thanks for pointing that out. – karlphillip May 19 '14 at 01:47
  • Appears to be a bug in Qt (although it might be in your code, I'm not familiar with Qt and whether there's some state that affects the drawing). I would try one of the other overloads of `drawImage`. – Cheers and hth. - Alf May 19 '14 at 01:56

1 Answers1

2

I found out that in these situations you need to call prepareGeometryChange() to let the parent know that the size/position of your widget has changed, and that it needs to query the new geometry to be able to paint it correctly to the screen.

This will make the parent invoke boundingRect() on your widget, so it's your responsibility to implement it:

void NewQMLitem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    prepareGeometryChange()
    painter->drawImage(200, 0, *image);
}

QRectF NewQMLitem::boundingRect() const
{
    return QRectF(m_x, m_y, m_width, m_height);
}
karlphillip
  • 92,053
  • 36
  • 243
  • 426