[PyQt] Strange mouse event and drag/drop behaviour in QGraphicsItem

Stefan Larsson lastsys at gmail.com
Sun Oct 25 15:11:35 GMT 2009


I am trying to resend this since sending source code as an attachment did
not seem to work properly when sending to this list.

I have been struggling for a while with strange and/or inconsistent mouse
event and drag/drop behaviour in QGraphicsItem where Windows differ from
Linux and OSX. I hope someone who have understood the mouse event system
could enlighten me?

The attached test-case shows a simple QGraphicsView with a QGraphicsScene.

When running it and pressing the left mouse button over one of the green
circles I get the following output in Windows 7 (PyQt 4.6):
1 Scene: mousePressEvent
2 Item: mousePressEvent
when releasing the left mouse button I get the following output:
3 View: mouseReleaseEvent
4 Scene: mouseReleaseEvent
5 Item: mouseReleaseEvent

The output is the same in Ubuntu 9.10 beta. (PyQt 4.6-1).

Now, if the method mousePressEvent in the Item class is changed by
uncommenting the "super" call (row 89) the output is changed:
1 Scene: mousePressEvent
2 Item: mousePressEvent
3 View: mouseReleaseEvent
4 Scene: mouseReleaseEvent

I get the same output in both Windows 7 and Ubuntu 9.10.
Question 1: Why is not the mouseReleaseEvent reaching the Item in this case?


Next case:
Also uncomment rows 91-97 in mousePressEvent of the Item class.
When clicking left mouse button in the same way as previously and holding it
down I get the following output in Windows 7:
1 Scene: mousePressEvent
2 Item: mousePressEvent
and when releasing the mouse button no additional output is received.

In Ubuntu 9.10, however, I get the following output:
1 Scene: mousePressEvent
2 Item: mousePressEvent
3 Item: dragEnterEvent
4 Item: dragMoveEvent
and when releasing the mouse button:
5 Item: dropEvent
QGraphicsItem::ungrabMouse: not a mouse grabber

Windows does not get the drag events until the mouse is actually moved.
Question 2: How should the inconsistency in drag events be handled?

In the Qt-documentation about QGraphicsItem is saying that:
" The mouse press event decides which item should become the mouse grabber
(see QGraphicsScene::
mouseGrabberItem <qgraphicsscene.html#mouseGrabberItem>()). If you do not
reimplement this function, the press event will propagate to any topmost
item beneath this item, and no other mouse events will be delivered to this
item."

I am not entirely sure how I should relate to this in this case... Any best
practices?

Thanks,
Stefan Larsson

Source:

import sys
import time

from PyQt4.QtCore import *
from PyQt4.QtGui import *

count = 0

def status(message):
    global count
    count += 1
    print count, message

class View(QGraphicsView):
    def __init__(self):
        super(View, self).__init__()
        self.setAcceptDrops(True)
        self.setRenderHints(QPainter.Antialiasing)
        self.setBackgroundBrush(Qt.darkGreen)

        scene = Scene(self)

        self.setScene(scene)

        item1 = Item()
        item2 = Item()
        item1.setPos(100,200)
        item2.setPos(300,200)

        scene.addItem(item1)
        scene.addItem(item2)

    def mouseReleaseEvent(self, event):
        status("View: mouseReleaseEvent")
        super(View, self).mouseReleaseEvent(event)

class Scene(QGraphicsScene):
    def __init__(self, parent):
        super(Scene, self).__init__(parent)
        self.setSceneRect(0, 0, 400, 400)

    def mousePressEvent(self, event):
        status("Scene: mousePressEvent")
        super(Scene, self).mousePressEvent(event)

    def mouseReleaseEvent(self, event):
        status("Scene: mouseReleaseEvent")
        super(Scene, self).mouseReleaseEvent(event)

class Item(QGraphicsItem):
    def __init__(self):
        super(Item, self).__init__()
        #self.setAcceptHoverEvents(True)
        self.setAcceptDrops(True)

        self.hovering = False

    def boundingRect(self):
        return QRectF(-42.0, -42.0, 84.0, 84.0)

    def paint(self, painter, option, widget):
        if self.hovering:
            color = Qt.yellow
        else:
            color = Qt.green

        r = QRectF(-40.0, -40.0, 80.0, 80.0)

        path = QPainterPath()
        path.addEllipse(r)
        painter.fillPath(path, QBrush(color))

        painter.setPen(QPen(QBrush(Qt.black), 2.0))
        painter.drawEllipse(r)

    def hoverEnterEvent(self, event):
        status("Item: hoverEnterEvent")
        self.hovering = True
        super(Item, self).hoverEnterEvent(event)

    def hoverLeaveEvent(self, event):
        status("Item: hoverLeaveEvent")
        self.hovering = False
        super(Item, self).hoverLeaveEvent(event)

    def mousePressEvent(self, event):
        status("Item: mousePressEvent")
        event.accept()
        super(Item, self).mousePressEvent(event)

        drag = QDrag(event.widget())
        mime_data = QMimeData()
        encoded_data = QByteArray()
        encoded_data.append('test')
        mime_data.setData('text/plain', encoded_data)
        drag.setMimeData(mime_data)
        drag.exec_(Qt.CopyAction)

    def mouseReleaseEvent(self, event):
        status("Item: mouseReleaseEvent")
        super(Item, self).mouseReleaseEvent(event)

    def dropEvent(self, event):
        status("Item: dropEvent")
        super(Item, self).dropEvent(event)

    def dragEnterEvent(self, event):
        status("Item: dragEnterEvent")
        super(Item, self).dragEnterEvent(event)

    def dragLeaveEvent(self, event):
        status("Item: dragLeaveEvent")
        super(Item, self).dragLeaveEvent(event)

    def dragMoveEvent(self, event):
        status("Item: dragMoveEvent")
        super(Item, self).dragMoveEvent(event)

    def mouseMoveEvent(self, event):
        status("Item: mouseMoveEvent")
        super(Item, self).mouseMoveEvent(event)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = View()
    view.show()
    sys.exit(app.exec_())
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20091025/ee8afb9e/attachment-0001.html


More information about the PyQt mailing list