Solved How to make a QGraphicsProxyWidget process mouse and key events before the QGraphicsView in which's scene its placed in?
I place QGraphicsProxyWidgets in a QGraphicsView and want them to receive any mouse and key events before the QGraphicsView receives them. Because several items exist in the scene which I can click on but I, of course, don't want them to be selected, dragged or anything (I do this manually in the mouseevent methods of QGraphicsView) when clicking on something in a proxy widget that is currently hovering over them.
Is this easily possible?
I think I could install an event filter that checks for the geometry of every proxy whether it contains the mouse events position, but I don't think it is a nice way to do it since I would have to check for all my proxies manually.
I am using PySide2 but it is more a general Qt question.
Thanks for answers!
I place QGraphicsProxyWidgets in a QGraphicsView and want them to receive any mouse and key events before the QGraphicsView receives them
without judging if thats good design or not, you can install an eventfilter on the QGraphicsView's viewport widget.
which is what I suggested isn't it?
Well, I handle some items interaction stuff in the qgraphicsview's mouse event methods, so I run into this issue. As I wrote, this would be bad design, so I wonder if there is a better way to achieve the same result.
Ok, I think I kind of have a workaround but I doubt it to be nice:
in my custom view, instead of doing:
def mousePressEvent(self, event): # my stuff ... QGraphicsView.mousePressEvent(self, event)
I can do
def mousePressEvent(self, event): QGraphicsView.mousePressEvent(self, event) # my stuff ...
This enables me to process the event in the proxy's widget before I do my manual stuff in the view.
Right now, this would work for me but I have a feeling that long term this is very bad design. Is it?
Hi I am not not sure why it would be bad design as its the normal way of extending an object via
virtual functions. Its very common to call the base implementation and then do custom processing.
Oh really? Ok, I wasn't used to it but if this is a common way, I'm very happy!
I have one more question about this: the proxy's event methods get called before I do my custom processing in the view but I want to block custom processing in the view if the events were received in a proxy. But how can I determine in the view whether the event has been passed to and accepted in a proxy widget?
event.accept()in my proxy widget does not accept the QGraphicsView's event, so the following code in my view
def mousePressEvent(self, event): event.setAccepted(False) QGraphicsView.mousePressEvent(self, event) if event.isAccepted(): return # my stuff
would not work
Niagarer last edited by
Seems like this question was kind of ridiculous...
I am not sure how conventional this solution is, but I now ended up with the following, maybe it helps someone:
QGraphicsProxyWidgetand added things like that:
from PySide2.QtWidgets import QGraphicsProxyWidget class FlowProxyWidget(QGraphicsProxyWidget): def __init__(self, flow, parent=None): super(FlowProxyWidget, self).__init__(parent) self.flow = flow def mousePressEvent(self, arg__1): self.flow.ignore_mouse_event = True QGraphicsProxyWidget.mousePressEvent(self, arg__1) ...
And my qgraphicsview checks for this
ignore_mouse_eventvariable like that:
def mousePressEvent(self, event): # there might be a proxy widget meant to receive the event instead of the flow QGraphicsView.mousePressEvent(self, event) if self.ignore_mouse_event: self.ignore_mouse_event = False return print('mouse press event in flow') # ... my own stuff
Qt's behaviour is kind of disturbing in this situation. Of course, proxy widgets are placed inside a
qgraphicsviewbut the fact that the view itself receives events before
qproxywidgetsand their widget even when clicking directly on the proxywidget sounds wired to me. I probably just don't get the concept :)
Might not be the most beautiful solution but it works for me for now.