Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. QGestureRecognizer.registerRecognizer() crashes using PySide2
Forum Updated to NodeBB v4.3 + New Features

QGestureRecognizer.registerRecognizer() crashes using PySide2

Scheduled Pinned Locked Moved Unsolved Qt for Python
19 Posts 4 Posters 1.7k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    nutrx
    wrote on last edited by
    #1

    I'm trying to register custom gestures in a QGraphicsView using PySide2. Calling

            pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
    

    results in a crash without any error. I couldn't find anything in the docs specifying the process of registering a gesture recognizer using PySide2. The following example reproduces the crash:

    class View(QGraphicsView):
        def __init__(self):
            super().__init__()
            scene = QGraphicsScene(self)
            scene.setSceneRect(0, 0, self.width(), self.height())
            self.setScene(scene)
    
            recognizer = PanGestureRecognizer()
            pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
            self.grabGesture(pan_gesture_id)
    

    am I missing anything there?

    JonBJ 1 Reply Last reply
    0
    • N nutrx

      I'm trying to register custom gestures in a QGraphicsView using PySide2. Calling

              pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
      

      results in a crash without any error. I couldn't find anything in the docs specifying the process of registering a gesture recognizer using PySide2. The following example reproduces the crash:

      class View(QGraphicsView):
          def __init__(self):
              super().__init__()
              scene = QGraphicsScene(self)
              scene.setSceneRect(0, 0, self.width(), self.height())
              self.setScene(scene)
      
              recognizer = PanGestureRecognizer()
              pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
              self.grabGesture(pan_gesture_id)
      

      am I missing anything there?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @nutrx
      If you have PyQt5 installed/available, the usual is to try it there. If same code works, blame PySide2....

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        Can you provide the full script you use to trigger the crash ?

        By the way:

        • which version of PySide2 are you using ?
        • which version of Python ?
        • on which OS ?
        • how did you install PySide2 ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        N 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          Can you provide the full script you use to trigger the crash ?

          By the way:

          • which version of PySide2 are you using ?
          • which version of Python ?
          • on which OS ?
          • how did you install PySide2 ?
          N Offline
          N Offline
          nutrx
          wrote on last edited by
          #4

          @SGaist sorry, should've added that

          from PySide2.QtWidgets import QMainWindow, QApplication, QGraphicsView, QGraphicsScene, QGestureRecognizer, QGesture
          from PySide2.QtGui import QTouchEvent
          from PySide2.QtCore import QEvent
          
          
          class PanGesture(QGesture):
              def __init__(self, parent=None):
                  super().__init__(parent)
          
                  self.pos = None
                  self.press = None
                  self.last = None
          
          class PanGestureRecognizer(QGestureRecognizer):
              """Not complete, just some test"""
              def create(self, target) -> QGesture:
                  return PanGesture()
          
              def reset(self, state: QGesture) -> None:
                  pass
          
              def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                  if event.type() == QEvent.TouchBegin:
                      touch_event: QTouchEvent = event
                      if len(touch_event.touchPoints()) == 1:
                          state.press = touch_event.touchPoints()[0]
                          state.pos = state.press
                          return QGestureRecognizer.MayBeGesture
                  elif event.type() == QEvent.TouchUpdate:
                      touch_event: QTouchEvent = event
                      state.last = state.pos
                      state.pos = touch_event.touchPoints()[0]
                      return QGestureRecognizer.TriggerGesture
          
          class View(QGraphicsView):
              def __init__(self):
                  super().__init__()
          
                  scene = QGraphicsScene(self)
                  scene.setSceneRect(0, 0, self.width(), self.height())
                  self.setScene(scene)
          
                  recognizer = PanGestureRecognizer()
                  pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
                  self.grabGesture(pan_gesture_id)
          
          class ViewWindow(QMainWindow):
              def __init__(self):
                  super().__init__()
                  self.setCentralWidget(View())
          
          if __name__ == '__main__':
              app = QApplication()
              widget = ViewWindow()
              widget.show()
              app.exec_()
          
          

          see View's constructor.

          • PySide2 5.15.2, installed via pip, inside python virtual environment
          • Python 3.9.0
          • Windows 10

          the GestureRecognizer probably doesn't work, I had just quickly put that together for some tests, but since I don't see any runtime error, I assume it's not the class custom GestureRecognizer what's causing the crash

          jeremy_kJ 1 Reply Last reply
          0
          • N nutrx

            @SGaist sorry, should've added that

            from PySide2.QtWidgets import QMainWindow, QApplication, QGraphicsView, QGraphicsScene, QGestureRecognizer, QGesture
            from PySide2.QtGui import QTouchEvent
            from PySide2.QtCore import QEvent
            
            
            class PanGesture(QGesture):
                def __init__(self, parent=None):
                    super().__init__(parent)
            
                    self.pos = None
                    self.press = None
                    self.last = None
            
            class PanGestureRecognizer(QGestureRecognizer):
                """Not complete, just some test"""
                def create(self, target) -> QGesture:
                    return PanGesture()
            
                def reset(self, state: QGesture) -> None:
                    pass
            
                def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                    if event.type() == QEvent.TouchBegin:
                        touch_event: QTouchEvent = event
                        if len(touch_event.touchPoints()) == 1:
                            state.press = touch_event.touchPoints()[0]
                            state.pos = state.press
                            return QGestureRecognizer.MayBeGesture
                    elif event.type() == QEvent.TouchUpdate:
                        touch_event: QTouchEvent = event
                        state.last = state.pos
                        state.pos = touch_event.touchPoints()[0]
                        return QGestureRecognizer.TriggerGesture
            
            class View(QGraphicsView):
                def __init__(self):
                    super().__init__()
            
                    scene = QGraphicsScene(self)
                    scene.setSceneRect(0, 0, self.width(), self.height())
                    self.setScene(scene)
            
                    recognizer = PanGestureRecognizer()
                    pan_gesture_id = QGestureRecognizer.registerRecognizer(recognizer)
                    self.grabGesture(pan_gesture_id)
            
            class ViewWindow(QMainWindow):
                def __init__(self):
                    super().__init__()
                    self.setCentralWidget(View())
            
            if __name__ == '__main__':
                app = QApplication()
                widget = ViewWindow()
                widget.show()
                app.exec_()
            
            

            see View's constructor.

            • PySide2 5.15.2, installed via pip, inside python virtual environment
            • Python 3.9.0
            • Windows 10

            the GestureRecognizer probably doesn't work, I had just quickly put that together for some tests, but since I don't see any runtime error, I assume it's not the class custom GestureRecognizer what's causing the crash

            jeremy_kJ Offline
            jeremy_kJ Offline
            jeremy_k
            wrote on last edited by
            #5

            After converting the example to run with PyQt5:

            $ python3 main.py 
            TypeError: invalid result from PanGestureRecognizer.recognize(), NoneType cannot be converted to PyQt5.QtWidgets.Result in this context
            Abort trap: 6
            

            PanGestureRecognizer.recognize is falling off the end and effectively returning None for anything other than a TouchBegin or TouchUpdate.

            Asking a question about code? http://eel.is/iso-c++/testcase/

            N 1 Reply Last reply
            0
            • jeremy_kJ jeremy_k

              After converting the example to run with PyQt5:

              $ python3 main.py 
              TypeError: invalid result from PanGestureRecognizer.recognize(), NoneType cannot be converted to PyQt5.QtWidgets.Result in this context
              Abort trap: 6
              

              PanGestureRecognizer.recognize is falling off the end and effectively returning None for anything other than a TouchBegin or TouchUpdate.

              N Offline
              N Offline
              nutrx
              wrote on last edited by
              #6

              @jeremy_k yes absolutely, I didn't pay attention to that method, because it still fails if I ignore otherwise, or everything from the beginning

                  def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                      return QGestureRecognizer.Ignore
              

              or in the example above:

                  def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                      if event.type() == QEvent.TouchBegin:
                          touch_event: QTouchEvent = event
                          if len(touch_event.touchPoints()) == 1:
                              state.press = touch_event.touchPoints()[0]
                              state.pos = state.press
                              return QGestureRecognizer.MayBeGesture
                      elif event.type() == QEvent.TouchUpdate:
                          touch_event: QTouchEvent = event
                          state.last = state.pos
                          state.pos = touch_event.touchPoints()[0]
                          return QGestureRecognizer.TriggerGesture
                      return QGestureRecognizer.Ignore
              

              Shouldn't that be sufficient?

              jeremy_kJ 1 Reply Last reply
              0
              • N nutrx

                @jeremy_k yes absolutely, I didn't pay attention to that method, because it still fails if I ignore otherwise, or everything from the beginning

                    def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                        return QGestureRecognizer.Ignore
                

                or in the example above:

                    def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                        if event.type() == QEvent.TouchBegin:
                            touch_event: QTouchEvent = event
                            if len(touch_event.touchPoints()) == 1:
                                state.press = touch_event.touchPoints()[0]
                                state.pos = state.press
                                return QGestureRecognizer.MayBeGesture
                        elif event.type() == QEvent.TouchUpdate:
                            touch_event: QTouchEvent = event
                            state.last = state.pos
                            state.pos = touch_event.touchPoints()[0]
                            return QGestureRecognizer.TriggerGesture
                        return QGestureRecognizer.Ignore
                

                Shouldn't that be sufficient?

                jeremy_kJ Offline
                jeremy_kJ Offline
                jeremy_k
                wrote on last edited by
                #7

                @nutrx said in QGestureRecognizer.registerRecognizer() crashes using PySide2:

                @jeremy_k yes absolutely, I didn't pay attention to that method, because it still fails if I ignore otherwise, or everything from the beginning

                    def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                        return QGestureRecognizer.Ignore
                

                ...

                Shouldn't that be sufficient?

                I'm not sure what you mean here. With the addition of the default Ignore, the application displays a window and doesn't do anything noteworthy in my environment. Are you still experiencing a crash?

                Asking a question about code? http://eel.is/iso-c++/testcase/

                N 1 Reply Last reply
                0
                • jeremy_kJ jeremy_k

                  @nutrx said in QGestureRecognizer.registerRecognizer() crashes using PySide2:

                  @jeremy_k yes absolutely, I didn't pay attention to that method, because it still fails if I ignore otherwise, or everything from the beginning

                      def recognize(self, state: QGesture, watched, event: QEvent) -> QGestureRecognizer.Result:
                          return QGestureRecognizer.Ignore
                  

                  ...

                  Shouldn't that be sufficient?

                  I'm not sure what you mean here. With the addition of the default Ignore, the application displays a window and doesn't do anything noteworthy in my environment. Are you still experiencing a crash?

                  N Offline
                  N Offline
                  nutrx
                  wrote on last edited by
                  #8

                  @jeremy_k yes, exactly. I just tried to get it to run, so I could move on from there. But it still crashes the same as before. Sorry, I don't have PyQt set up rn

                  jeremy_kJ 1 Reply Last reply
                  0
                  • N nutrx

                    @jeremy_k yes, exactly. I just tried to get it to run, so I could move on from there. But it still crashes the same as before. Sorry, I don't have PyQt set up rn

                    jeremy_kJ Offline
                    jeremy_kJ Offline
                    jeremy_k
                    wrote on last edited by
                    #9

                    PanGestureRecognizer doesn't have an __init__ to call QGestureRecognizer.__init__. I vaguely recall reports of misbehavior using PyQt if a Qt object's constructor isn't invoked. This may have been limited to QObjects. It might not apply to PySide. Either way, it's an inexpensive experiment to run. QGestureRecognizer's C++ constructor is empty, but there may be some bookkeeping on the Python side.

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    N 1 Reply Last reply
                    0
                    • jeremy_kJ jeremy_k

                      PanGestureRecognizer doesn't have an __init__ to call QGestureRecognizer.__init__. I vaguely recall reports of misbehavior using PyQt if a Qt object's constructor isn't invoked. This may have been limited to QObjects. It might not apply to PySide. Either way, it's an inexpensive experiment to run. QGestureRecognizer's C++ constructor is empty, but there may be some bookkeeping on the Python side.

                      N Offline
                      N Offline
                      nutrx
                      wrote on last edited by
                      #10

                      @jeremy_k you mean, I should try just calling QGestureRecognizer's __init__ in PanGestureRecognizer.__init__? I would've guessed that's ambiguous, or does instanciation lead to a direct call of the C++ parent constructor instead of the parent's __init__ in Python? However, I just tried, still no luck :/

                      jeremy_kJ 1 Reply Last reply
                      0
                      • N nutrx

                        @jeremy_k you mean, I should try just calling QGestureRecognizer's __init__ in PanGestureRecognizer.__init__? I would've guessed that's ambiguous, or does instanciation lead to a direct call of the C++ parent constructor instead of the parent's __init__ in Python? However, I just tried, still no luck :/

                        jeremy_kJ Offline
                        jeremy_kJ Offline
                        jeremy_k
                        wrote on last edited by
                        #11
                        class PanGestureRecognizer(QGestureRecognizer):
                            def __init__(self):
                                super().__init__()
                        

                        This doesn't seem to be necessary with pure python classes. The wording of object.__init__ led me to believe that it was, but a test suggests that the base class __init__ is called if no derived __init__ is defined.

                        Asking a question about code? http://eel.is/iso-c++/testcase/

                        JonBJ 1 Reply Last reply
                        0
                        • jeremy_kJ jeremy_k
                          class PanGestureRecognizer(QGestureRecognizer):
                              def __init__(self):
                                  super().__init__()
                          

                          This doesn't seem to be necessary with pure python classes. The wording of object.__init__ led me to believe that it was, but a test suggests that the base class __init__ is called if no derived __init__ is defined.

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @jeremy_k
                          Well, in Python just like in, say, C++, if you do not define your own __init__() (constructor in C++) the language will always cause the base class's __init__()/constructor. If you do define your own, you must then explicitly call the base class __init__()/constructor, in either language. in Python.

                          [EDIT As @jeremy_k pointed out below, I was wrong to say this applies in all C++ cases. Let's leave it as: in Python, if you define any derived __init__() you must (should) explicitly call the base __init__() from there; but if you do not define a derived __init__() the base one will still be called.]

                          I vaguely recall reports of misbehavior using PyQt if a Qt object's constructor isn't invoked

                          I don't know if somehow PySide2/PyQt requires you to explicitly define your own __init__() and call the base, unless you have some reference for that?

                          jeremy_kJ 1 Reply Last reply
                          1
                          • JonBJ JonB

                            @jeremy_k
                            Well, in Python just like in, say, C++, if you do not define your own __init__() (constructor in C++) the language will always cause the base class's __init__()/constructor. If you do define your own, you must then explicitly call the base class __init__()/constructor, in either language. in Python.

                            [EDIT As @jeremy_k pointed out below, I was wrong to say this applies in all C++ cases. Let's leave it as: in Python, if you define any derived __init__() you must (should) explicitly call the base __init__() from there; but if you do not define a derived __init__() the base one will still be called.]

                            I vaguely recall reports of misbehavior using PyQt if a Qt object's constructor isn't invoked

                            I don't know if somehow PySide2/PyQt requires you to explicitly define your own __init__() and call the base, unless you have some reference for that?

                            jeremy_kJ Offline
                            jeremy_kJ Offline
                            jeremy_k
                            wrote on last edited by
                            #13

                            @JonB said in QGestureRecognizer.registerRecognizer() crashes using PySide2:

                            @jeremy_k
                            Well, in Python just like in, say, C++, if you do not define your own __init__() (constructor in C++) the language will always cause the base class's __init__()/constructor. If you do define your own, you must then explicitly call the base class __init__()/constructor, in either language.

                            That's inaccurate for C++ base class default constructors. The compiler will insert a call to the base constructor if the programmer does not. Explicit invocation is only required if there are arguments to pass.

                            Asking a question about code? http://eel.is/iso-c++/testcase/

                            JonBJ 1 Reply Last reply
                            1
                            • jeremy_kJ jeremy_k

                              @JonB said in QGestureRecognizer.registerRecognizer() crashes using PySide2:

                              @jeremy_k
                              Well, in Python just like in, say, C++, if you do not define your own __init__() (constructor in C++) the language will always cause the base class's __init__()/constructor. If you do define your own, you must then explicitly call the base class __init__()/constructor, in either language.

                              That's inaccurate for C++ base class default constructors. The compiler will insert a call to the base constructor if the programmer does not. Explicit invocation is only required if there are arguments to pass.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by
                              #14

                              @jeremy_k
                              You are quite correct, and thank you for pointing this out. Partly I was unconsciously thinking of constructors with parameters, and partly I make slips as I swap between C#/C++/Python/JavaScript! I will correct my previous post, so as not to mislead.

                              1 Reply Last reply
                              0
                              • SGaistS Offline
                                SGaistS Offline
                                SGaist
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                You may have found a bug in the PySide2 implementation. Did you check if you have the same behaviour with PySide6 ?

                                Interested in AI ? www.idiap.ch
                                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                N 1 Reply Last reply
                                0
                                • SGaistS SGaist

                                  You may have found a bug in the PySide2 implementation. Did you check if you have the same behaviour with PySide6 ?

                                  N Offline
                                  N Offline
                                  nutrx
                                  wrote on last edited by
                                  #16

                                  @SGaist yes, same with PySide6

                                  1 Reply Last reply
                                  0
                                  • SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    Then you should go to the bug report system and see if there's already something there. If not, please consider opening a new issue providing your minimal runnable script that shows that behaviour.

                                    Interested in AI ? www.idiap.ch
                                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    1 Reply Last reply
                                    0
                                    • N Offline
                                      N Offline
                                      nutrx
                                      wrote on last edited by nutrx
                                      #18

                                      Yeah, just found a bugreport reporting this exact issue. It's open since 2015..........
                                      I am really confused. I mean ... isn't this making the whole custom gesture recognizer system completely unsuable?

                                      1 Reply Last reply
                                      0
                                      • SGaistS Offline
                                        SGaistS Offline
                                        SGaist
                                        Lifetime Qt Champion
                                        wrote on last edited by
                                        #19

                                        It's an issue on Python and it has likely not been used that much with that language. You can add a comment on the issue to remind the current assigned person that this is still not solved.

                                        Interested in AI ? www.idiap.ch
                                        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                        1 Reply Last reply
                                        0

                                        • Login

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • Users
                                        • Groups
                                        • Search
                                        • Get Qt Extensions
                                        • Unsolved