Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to make a QGraphicsProxyWidget process mouse and key events before the QGraphicsView in which's scene its placed in?



  • Hi,
    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!


  • Moderators

    @Niagarer said in How to make a QGraphicsProxyWidget receive 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

    without judging if thats good design or not, you can install an eventfilter on the QGraphicsView's viewport widget.



  • @raven-worx
    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?


  • Lifetime Qt Champion

    @Niagarer
    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.



  • @mrjj
    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?
    Calling 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



  • 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:

    I subclassed QGraphicsProxyWidget and 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_event variable 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 qgraphicsview but the fact that the view itself receives events before qproxywidgets and 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.


Log in to reply