Issue
If you have a QGraphicsEllipseItem with that is much wider than it is high (flattened), it paints outside its own bounds. This means it doesn't paint properly, and leaves artifacts on the screen when you drag it around. This reproduces the problem (apologies to non-Pythonistas, but it should be quite understandable to C++ers):
import sys
from PySide import QtCore, QtGui
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
scene = QtGui.QGraphicsScene()
scene.setSceneRect(0, 0, 400, 400)
ellipse = QtGui.QGraphicsEllipseItem(QtCore.QRectF(0, 0, 320, 5))
ellipse.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
ellipse.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
ellipse.setPos(40, 200)
ellipse.setPen(QtGui.QPen(QtCore.Qt.red, 1))
scene.addItem(ellipse)
view = QtGui.QGraphicsView(scene)
view.show()
sys.exit(app.exec_())
The key point is that the QGraphicsEllipseItem has a width of 320 and a height of just 5. If you select the ellipse, the dashed line of the selection box is painted at the bounds of the item, and you can see that the left and right edges of the ellipse are outside of those bounds. If you then drag the item around you will get artifacts.
This is on Windows 7 64bit, using PySide 1.1.2, if it matters.
If you turn on anti-aliasing (e.g. view.setRenderHint(QtGui.QPainter.Antialiasing)
) the ellipse is painted within its bounds and everything is fine.
I'd rather have the option of painting aliased or anti-aliased but as a last resort I can just always paint anti-aliased unless anyone has a better solution. I've subclassed QGraphicsEllipseItem and put a large amount of padding around the base-class's bounding rect, something like:
def boundingRect(self):
return QGraphicsEllipseItem.boundingRect(self).adjusted(-40, -40, 40, 40)
and this solves the problem in a lot of cases, but if the ellipse is very large you can get a long way outside of the bounds, so it's difficult to know how much padding to add, and in any case this is a fairly crappy solution as it means my bounds are miles out in most cases (implications for collision detection etc).
You can also stop the artifacts by changing the update mode on the view, i.e.:
view.setViewportUpdateMode(QtGui.QGraphicsView.FullViewportUpdate)
It seems a bit sad to have to do this to deal with the painting of one GraphicsItem type just in the case that it's very flattened ...
I guess I could try to paint the thing 'properly' in my own QGraphicsEllipseItem subclass, but I suspect that the base class is just telling the painter to draw an ellipse, so I'd have to mess around a lot to come up with my own ellipse drawing algorithm that doesn't use the painter one ...
Any other ideas? What seems like the least-bad option? I'm leaning towards just having FullViewportUpdate switched on.
Solution
It is a problem with QPen.
If you use a QPen with a greater width (1.2 for example), the problem disappears (if I remember correctly, by default, for the joins, QPen extends the lines while it finds an intersection).
Answered By - Dimitry Ernot
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.