Search code examples
qtpyqtpysideqgraphicsviewqgraphicsscene

PySide moving QGraphicsPixmapItem jumps to upper left corner of scene


I am writing an application that allows a user to place images on a QGraphicsScene (contained within a QGraphicsView) by clicking on a blank area and then move them about using mousemoveevent. The images are created using a subclassed QGraphicsPixmapItem.

Here's the problem: The very first attempt at moving an item works as expected. However, for all subsequent moves the selected item immediately jumps to the upper left corner of the scene. Here is the code:

import sys
from PySide import QtGui,QtCore

class TestPixmapItem(QtGui.QGraphicsPixmapItem):
    def __init__(self, imagename, position, parent=None):
        QtGui.QGraphicsPixmapItem.__init__(self, parent)

        px = QtGui.QPixmap(imagename)
        self.setPixmap(px)

        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)

        # set position
        self.setPos(position.x(),position.y())

    def mouseReleaseEvent(self,e):
        self.setSelected(False)

    def mouseMoveEvent(self, e):
        QtGui.QGraphicsPixmapItem.mouseMoveEvent(self, e)


class GfxScene(QtGui.QGraphicsScene):
    def __init__(self, parent=None):
        #build parent user interface
        super(GfxScene, self).__init__(parent)

    def mousePressEvent(self, e):
        if(self.itemAt(e.scenePos().x(),e.scenePos().y()) == None):
            pixmapItem = TestPixmapItem('test.png',e.scenePos())
            self.addItem(pixmapItem)
        else:
            QtGui.QGraphicsScene.mousePressEvent(self,e); 


class MainForm(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MainForm, self).__init__(parent)

        scene = GfxScene(self)
        scene.setSceneRect(QtCore.QRect(0, 0, 800, 800))

        view = QtGui.QGraphicsView()
        view.setScene(scene)
        view.setSceneRect(scene.sceneRect())
        #view.setGeometry(QtCore.QRect(0, 0, 800, 800))
        self.setCentralWidget(view)


def main():
    #This function means this was run directly, not called from another python file.
    app = QtGui.QApplication.instance()
    if app == None:
            app = QtGui.QApplication(sys.argv)
    myapp = MainForm()
    myapp.show()

    sys.exit(app.exec_())


if __name__ == '__main__':
    main() 

Any help would be appreciated!


Solution

  • You should call the QtGui.QGraphicsPixmapItem.mouseReleaseEvent(self, e) when you override the mouse release event, see : http://goo.gl/ChSYP

    import sys
    from PySide import QtGui,QtCore
    
    class TestPixmapItem(QtGui.QGraphicsPixmapItem):
        def __init__(self, imagename, position, parent=None):
            QtGui.QGraphicsPixmapItem.__init__(self, parent)
    
        px = QtGui.QPixmap(imagename)
        self.setPixmap(px)
    
        self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)
        self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True)
    
        # set position
        self.setPos(position.x(),position.y())
    
    def mouseReleaseEvent(self,e):
        self.setSelected(False)
        QtGui.QGraphicsPixmapItem.mouseReleaseEvent(self, e) // here calling the event
    
    def mouseMoveEvent(self, e):
        QtGui.QGraphicsPixmapItem.mouseMoveEvent(self, e)
    
    
    class GfxScene(QtGui.QGraphicsScene):
        def __init__(self, parent=None):
            #build parent user interface
            super(GfxScene, self).__init__(parent)
    
    def mousePressEvent(self, e):
        if(self.itemAt(e.scenePos().x(),e.scenePos().y()) == None):
            pixmapItem = TestPixmapItem('test.png',e.scenePos())
            self.addItem(pixmapItem)
        else:
            QtGui.QGraphicsScene.mousePressEvent(self,e); 
    
    
    class MainForm(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainForm, self).__init__(parent)
    
        scene = GfxScene(self)
        scene.setSceneRect(QtCore.QRect(0, 0, 800, 800))
    
        view = QtGui.QGraphicsView()
        view.setScene(scene)
        view.setSceneRect(scene.sceneRect())
        #view.setGeometry(QtCore.QRect(0, 0, 800, 800))
        self.setCentralWidget(view)
    
    
    def main():
        #This function means this was run directly, not called from another python file.
        app = QtGui.QApplication.instance()
        if app == None:
            app = QtGui.QApplication(sys.argv)
        myapp = MainForm()
        myapp.show()
    
    sys.exit(app.exec_())
    
    
    if __name__ == '__main__':
        main()