[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