tags:

views:

506

answers:

2

Drawing on a QPicture should update its bounding rect. Like this:

>>> picture = QPicture()
>>> painter = QPainter(picture)
>>> picture.boundingRect()
QRect(0,0,0,0)
>>> painter.drawRect(20,20,50,50)
>>> picture.boundingRect()
QRect(20,20,50,50)

But if I draw text on it, the bounding rect isn't updated:

>>> picture = QPicture()
>>> painter = QPainter(picture)
>>> picture.boundingRect()
QRect(0,0,0,0)
>>> painter.drawText(10,10, "Hello, World!")
>>> picture.boundingRect()
QRect(0,0,0,0)

Obviously, it doesn't update the bounding rect.

Is there a way to make it repsect drawn text or do I have to do it manually? (Not too hard, but I hope that Qt can assist me here.)

A: 

Painting doesn't change the size of something in Qt. The main reason is this:

  • A component has to paint itself
  • The paint triggers a resize
  • The resize triggers painting -> endless loop

So the resize has to happen during the layout phase. After that, the bounds should not change.

To solve your problem, use QFontMetric to figure out how big your text is going to be during or close to the construction of your picture and then resize it accordingly.

[EDIT] Hm ... try to call end() before requesting the bounding rect. If that works, you've found a bug (can't see a reason why the bounding rect should not exist as you add elements...)

Aaron Digulla
I'm painting on a QPicture, which doesn't have a fixed size, but calculates the rect around all elements. I think you mistake QImage for QPicture.
Georg
+1  A: 

Take a look at these overload methods, where you must specify the Bounding Rectangle after the text parameter (which is apparently different than the rectangle in the first argument's position):

Draws the given text within the provided rectangle according to the specified flags. The boundingRect (if not null) is set to the what the bounding rectangle should be in order to enclose the whole text.

Doc 1

Doc 2

Update:

It appears if you want to generate a bounding rectangle for the drawText() method in advance, you just call the boundingRect() method on QPainter, which does the following:

Returns the bounding rectangle of the text as it will appear when drawn inside the given rectangle with the specified flags using the currently set font(); i.e the function tells you where the drawText() function will draw when given the same arguments.

If the text does not fit within the given rectangle using the specified flags, the function returns the required rectangle.

Doc 3

I linked to BoundingRect with QRectF output, but the information applies to the other versions as well.

So basically, pass the result of QPainter.boundingRect() into the boundingRect parameter of the QPainter.drawText() method (the second QRect argument).

Update 2:

I APOLOGIZE PROFUSELY for being so damn dense. I forgot that drawText works differently in PyQt than in Qt. The bounding rectangle is RETURNED by the drawText function (not passed in like Qt) and in addition, you have to specify alignment flags before you get a bounding rectangle given back to you. (I even included the p.end() as per Aaron Digulla's comment):

pic = Qt.QPicture()
p = QtGui.QPainter(pic)
brect = p.drawText(10,10,200,200, QtCore.Qt.AlignCenter, "blah")
p.end()
print brect
print pic.boundingRect()

Here is the output:

PyQt4.QtCore.QRect(100, 103, 20, 14)

PyQt4.QtCore.QRect(0, 0, 0, 0)

So it appears you will have to set the bounding rectangle yourself, though at least it is returned to you by the output of the drawText() method when passing in flags.

This does not seem like ideal behaviour, that you would have to set the bounding rectangle yourself. I hope someone else has the answer you're looking for, but I suspect you may want to report this bug.

Chris Cameron
The thing is, the bounding rect of the QPicture updates itself after any operation but drawing text. I know I can get the bounding rect of a text with those functions.
Georg
I was trying to imply it was not possible. I have updated my answer again, since I made the mistake of referring to some incorrect C++ doc for your PyQt code.
Chris Cameron
Thanks for your effort! I haven't gotten an ideal solution now (setting the bounding rect manually disables the automatic updating), but thanks again.
Georg