Fixed item context menus appearing after mouse has exited the item area.
This occurred because the scene does not receive mouse move events while a context menu is displayed. If the user right-clicks on a new location while the menu is open, then the click event is delieverd as if the mouse had not moved. Corrected by sending a just-in-time hover event immediately before mouse press, if the cursor has moved.
This commit is contained in:
parent
706fe92fdb
commit
4896de5ee4
@ -135,8 +135,13 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
def mousePressEvent(self, ev):
|
def mousePressEvent(self, ev):
|
||||||
#print 'scenePress'
|
#print 'scenePress'
|
||||||
QtGui.QGraphicsScene.mousePressEvent(self, ev)
|
QtGui.QGraphicsScene.mousePressEvent(self, ev)
|
||||||
#print "mouseGrabberItem: ", self.mouseGrabberItem()
|
|
||||||
if self.mouseGrabberItem() is None: ## nobody claimed press; we are free to generate drag/click events
|
if self.mouseGrabberItem() is None: ## nobody claimed press; we are free to generate drag/click events
|
||||||
|
if self.lastHoverEvent is not None:
|
||||||
|
# If the mouse has moved since the last hover event, send a new one.
|
||||||
|
# This can happen if a context menu is open while the mouse is moving.
|
||||||
|
if ev.scenePos() != self.lastHoverEvent.scenePos():
|
||||||
|
self.sendHoverEvents(ev)
|
||||||
|
|
||||||
self.clickEvents.append(MouseClickEvent(ev))
|
self.clickEvents.append(MouseClickEvent(ev))
|
||||||
|
|
||||||
## set focus on the topmost focusable item under this click
|
## set focus on the topmost focusable item under this click
|
||||||
@ -145,10 +150,6 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
if i.isEnabled() and i.isVisible() and int(i.flags() & i.ItemIsFocusable) > 0:
|
if i.isEnabled() and i.isVisible() and int(i.flags() & i.ItemIsFocusable) > 0:
|
||||||
i.setFocus(QtCore.Qt.MouseFocusReason)
|
i.setFocus(QtCore.Qt.MouseFocusReason)
|
||||||
break
|
break
|
||||||
#else:
|
|
||||||
#addr = sip.unwrapinstance(sip.cast(self.mouseGrabberItem(), QtGui.QGraphicsItem))
|
|
||||||
#item = GraphicsScene._addressCache.get(addr, self.mouseGrabberItem())
|
|
||||||
#print "click grabbed by:", item
|
|
||||||
|
|
||||||
def mouseMoveEvent(self, ev):
|
def mouseMoveEvent(self, ev):
|
||||||
self.sigMouseMoved.emit(ev.scenePos())
|
self.sigMouseMoved.emit(ev.scenePos())
|
||||||
@ -189,7 +190,6 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
def mouseReleaseEvent(self, ev):
|
def mouseReleaseEvent(self, ev):
|
||||||
#print 'sceneRelease'
|
#print 'sceneRelease'
|
||||||
if self.mouseGrabberItem() is None:
|
if self.mouseGrabberItem() is None:
|
||||||
#print "sending click/drag event"
|
|
||||||
if ev.button() in self.dragButtons:
|
if ev.button() in self.dragButtons:
|
||||||
if self.sendDragEvent(ev, final=True):
|
if self.sendDragEvent(ev, final=True):
|
||||||
#print "sent drag event"
|
#print "sent drag event"
|
||||||
@ -231,6 +231,8 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
|
|
||||||
prevItems = list(self.hoverItems.keys())
|
prevItems = list(self.hoverItems.keys())
|
||||||
|
|
||||||
|
#print "hover prev items:", prevItems
|
||||||
|
#print "hover test items:", items
|
||||||
for item in items:
|
for item in items:
|
||||||
if hasattr(item, 'hoverEvent'):
|
if hasattr(item, 'hoverEvent'):
|
||||||
event.currentItem = item
|
event.currentItem = item
|
||||||
@ -248,6 +250,7 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
|
|
||||||
event.enter = False
|
event.enter = False
|
||||||
event.exit = True
|
event.exit = True
|
||||||
|
#print "hover exit items:", prevItems
|
||||||
for item in prevItems:
|
for item in prevItems:
|
||||||
event.currentItem = item
|
event.currentItem = item
|
||||||
try:
|
try:
|
||||||
@ -257,10 +260,14 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
finally:
|
finally:
|
||||||
del self.hoverItems[item]
|
del self.hoverItems[item]
|
||||||
|
|
||||||
if hasattr(ev, 'buttons') and int(ev.buttons()) == 0:
|
# Update last hover event unless:
|
||||||
|
# - mouse is dragging (move+buttons); in this case we want the dragged
|
||||||
|
# item to continue receiving events until the drag is over
|
||||||
|
# - event is not a mouse event (QEvent.Leave sometimes appears here)
|
||||||
|
if (ev.type() == ev.GraphicsSceneMousePress or
|
||||||
|
(ev.type() == ev.GraphicsSceneMouseMove and int(ev.buttons()) == 0)):
|
||||||
self.lastHoverEvent = event ## save this so we can ask about accepted events later.
|
self.lastHoverEvent = event ## save this so we can ask about accepted events later.
|
||||||
|
|
||||||
|
|
||||||
def sendDragEvent(self, ev, init=False, final=False):
|
def sendDragEvent(self, ev, init=False, final=False):
|
||||||
## Send a MouseDragEvent to the current dragItem or to
|
## Send a MouseDragEvent to the current dragItem or to
|
||||||
## items near the beginning of the drag
|
## items near the beginning of the drag
|
||||||
@ -323,7 +330,6 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
acceptedItem = self.lastHoverEvent.clickItems().get(ev.button(), None)
|
acceptedItem = self.lastHoverEvent.clickItems().get(ev.button(), None)
|
||||||
else:
|
else:
|
||||||
acceptedItem = None
|
acceptedItem = None
|
||||||
|
|
||||||
if acceptedItem is not None:
|
if acceptedItem is not None:
|
||||||
ev.currentItem = acceptedItem
|
ev.currentItem = acceptedItem
|
||||||
try:
|
try:
|
||||||
@ -345,22 +351,9 @@ class GraphicsScene(QtGui.QGraphicsScene):
|
|||||||
if int(item.flags() & item.ItemIsFocusable) > 0:
|
if int(item.flags() & item.ItemIsFocusable) > 0:
|
||||||
item.setFocus(QtCore.Qt.MouseFocusReason)
|
item.setFocus(QtCore.Qt.MouseFocusReason)
|
||||||
break
|
break
|
||||||
#if not ev.isAccepted() and ev.button() is QtCore.Qt.RightButton:
|
|
||||||
#print "GraphicsScene emitting sigSceneContextMenu"
|
|
||||||
#self.sigMouseClicked.emit(ev)
|
|
||||||
#ev.accept()
|
|
||||||
self.sigMouseClicked.emit(ev)
|
self.sigMouseClicked.emit(ev)
|
||||||
return ev.isAccepted()
|
return ev.isAccepted()
|
||||||
|
|
||||||
#def claimEvent(self, item, button, eventType):
|
|
||||||
#key = (button, eventType)
|
|
||||||
#if key in self.claimedEvents:
|
|
||||||
#return False
|
|
||||||
#self.claimedEvents[key] = item
|
|
||||||
#print "event", key, "claimed by", item
|
|
||||||
#return True
|
|
||||||
|
|
||||||
|
|
||||||
def items(self, *args):
|
def items(self, *args):
|
||||||
#print 'args:', args
|
#print 'args:', args
|
||||||
items = QtGui.QGraphicsScene.items(self, *args)
|
items = QtGui.QGraphicsScene.items(self, *args)
|
||||||
|
@ -355,6 +355,9 @@ class HoverEvent(object):
|
|||||||
return Point(self.currentItem.mapFromScene(self._lastScenePos))
|
return Point(self.currentItem.mapFromScene(self._lastScenePos))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
if self.exit:
|
||||||
|
return "<HoverEvent exit=True>"
|
||||||
|
|
||||||
if self.currentItem is None:
|
if self.currentItem is None:
|
||||||
lp = self._lastScenePos
|
lp = self._lastScenePos
|
||||||
p = self._scenePos
|
p = self._scenePos
|
||||||
|
Loading…
Reference in New Issue
Block a user