While trying to implement a scene where item sizes do not change but distances between items get magnified I encountered this problem with the following code which draws a rectangle and the text "A". Now if I set the flag ItemIgnoresTransformations on the rectangle item, zooming in causes the rectangle to vanish (click and drag mouse button around the rectangle). But that does not happen in case of the text. Also, the new viewport area set by fitInView is very different for I asked for:
import sys
from PyQt4 import QtCore, QtGui
class GV(QtGui.QGraphicsView):
def __init__(self, *args, **kwargs):
QtGui.QGraphicsView.__init__(self, *args, **kwargs)
def mousePressEvent(self, event):
pos = QtCore.QPoint(event.pos())
self.startPos = pos
def mouseReleaseEvent(self, event):
pos = QtCore.QPoint(event.pos())
self.endPos = pos
rect = QtCore.QRect(self.startPos, self.endPos)
sceneRect = self.mapToScene(rect).boundingRect()
print 'Selected area: viewport coordinate:', rect, \
', scene coordinate:', sceneRect
self.fitInView(sceneRect)
print 'new viewport in scene coordinates:', \
self.mapToScene(self.viewport().geometry()).boundingRect()
class Scene(QtGui.QGraphicsScene):
def __init__(self, *args, **kwargs):
QtGui.QGraphicsScene.__init__(self, *args, **kwargs)
self.itemA = QtGui.QGraphicsSimpleTextItem('A')
self.itemA.setPos(20, 20)
self.itemA.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, True)
self.addItem(self.itemA)
self.itemB = QtGui.QGraphicsRectItem(30, 50, 20, 20)
self.addItem(self.itemB)
self.itemB.setFlag(QtGui.QGraphicsItem.ItemIgnoresTransformations, True)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
widget = QtGui.QMainWindow()
scene = Scene()
view = GV(scene, widget)
widget.setCentralWidget(view)
widget.show()
app.exec_()
Any explanations will be appreciated!
In fact, the rectangle does not vanish. But it moves around "strangely".
self.itemB = QtGui.QGraphicsRectItem(30, 50, 20, 20)
This line may not be what you want. This creates an item and puts a rectangle/square starting from (30, 50)
in local coordinates. Then you add this to the scene. This gives you an item anchored at (0, 0)
, spans up to (50, 70)
but draws a rectangle only in the bottom right 20x20
.
When you set ItemIgnoresTransformations
, item can't do its regular transformations in case of a zoom. Scene zooms in, for item to ignore this transformation, it kind of "shrinks" itself. But it's still anchored at (0, 0)
and the rectangle is at the bottom-right, so the drawn rectangle moves toward the upper-left.
Solution is rather simple. Don't create your rectangle in local coordinates, i.e. your rectangle should start from (0, 0)
and you should position it explicitly. Which translates to this:
self.itemB = QtGui.QGraphicsRectItem(0, 0, 20, 20)
self.itemB.setPos(30, 50)