Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Touchscreen QPushButton does not emit released()
Forum Update on Monday, May 27th 2025

Touchscreen QPushButton does not emit released()

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 3 Posters 739 Views
  • 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.
  • johngodJ johngod

    @bigguiness Hi
    If you are using widgets I don't have a clue how to fix this, if using qml is a option, this can be fixed with MultiPointTouchArea and TouchPoint but with some limitations. TouchPoint does not have press and release signals, you would have to use onPressedChanged handler. Another limitation would be the number of jog buttons pressed / released at the same time would be limited to the maximum avaible touch points in the screen (usually is 10, so probably this is not a problem, I dont see anyone using more than 10 fingers at the same time). You would have to "dinamically" "assing" each TouchPoint to a jog button, based on the order of the touchs being pressed and their screen position, which is a bit of work, but doable.

    Some pseudo code:

    MultiPointTouchArea {
        touchPoints: [
            TouchPoint {
                id: point1
                onPressedChanged: {
                    if (pressed) { //pressed
                        
                        if ( x, y inside jog button1 screen position)
                            jogBtn1.press()
                        
                        if ( x, y inside jog button2)
                            jogBtn2.press()
                       //add more buttons
                    }
                    else { //released
                        if ( x, y inside jog button1)
                            jogBtn1.release()
                        
                        if ( x, y inside jog button2)
                            jogBtn2.release()
                       //add more buttons
                    }
                }
            },
            TouchPoint {
                id: point2
                onPressedChanged: {
                    if (pressed) { //pressed
                        
                        if ( x, y inside jog button1 screen position)
                            jogBtn1.press()
                        
                        if ( x, y inside jog button2)
                            jogBtn2.press()
                       //add more buttons
                    }
                    else { //released
                        if ( x, y inside jog button1)
                            jogBtn1.release()
                        
                        if ( x, y inside jog button2)
                            jogBtn2.release()
                       //add more buttons
                    }
                }
            },
            //repeat same stuff for TouchPoint 3}
    
    JoeCFDJ Offline
    JoeCFDJ Offline
    JoeCFD
    wrote on last edited by
    #4

    @johngod said in Touchscreen QPushButton does not emit released():

    MultiPointTouchArea

    Do the similar thing with touch events?

    protected:
        bool event(QEvent *event) override
        {
            if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchUpdate || event->type() == QEvent::TouchEnd)
            {
                QTouchEvent* touchEvent = static_cast<QTouchEvent*>(event);
                
                foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints())
                {
                    // Handle touch events here
                    qDebug() << "Touch event ID: " << touchPoint.id()
                             << "Pos: " << touchPoint.pos()
                             << "Pressure: " << touchPoint.pressure();
                }
                
                return true; // Mark the event as handled
            }
    
            return QWidget::event(event);
        }
    
    bigguinessB 1 Reply Last reply
    0
    • JoeCFDJ JoeCFD

      @johngod said in Touchscreen QPushButton does not emit released():

      MultiPointTouchArea

      Do the similar thing with touch events?

      protected:
          bool event(QEvent *event) override
          {
              if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchUpdate || event->type() == QEvent::TouchEnd)
              {
                  QTouchEvent* touchEvent = static_cast<QTouchEvent*>(event);
                  
                  foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints())
                  {
                      // Handle touch events here
                      qDebug() << "Touch event ID: " << touchPoint.id()
                               << "Pos: " << touchPoint.pos()
                               << "Pressure: " << touchPoint.pressure();
                  }
                  
                  return true; // Mark the event as handled
              }
      
              return QWidget::event(event);
          }
      
      bigguinessB Offline
      bigguinessB Offline
      bigguiness
      wrote on last edited by
      #5

      @JoeCFD
      I tried adding the event() override to see if I could do something in it to handle the multi-touch event. Right now it's just a big switch() that outputs a qDebug() message for every event->type() so I can see what is happening. Once I verified it worked I started disabling the message for various events (Enter, Move, Leave, Paint, etc.) to filter out only the ones I am interested in.

      The output I am seeing now is not quite what I expected.

      My "jog" buttons are actually handled in a widget that I put on the dialog.

      namespace Ui {
      class Jogger;
      }
      
      class Jogger : public QWidget {
          Q_OBJECT
      public:
          // Constructor/Destructor
          // public methods
      protected:
          bool event(QEvent *event) override;
          ....
      };
      

      All the buttons are connected to the QPushButton::pressed() and QPushButton::released() signals using lambdas. I have added some qDebug() in each to debug the press/release.

      When I run code on a Windows machine (non-touchscreen) and use a mouse, I see debug like this when I press/release a button:

      Jogger : buttonXp pressed
      Jogger : buttonXp released
      

      I always get a press/release for a single button. If I click on a button and move the mouse off the button then back on the button then release, I see something like this:

      Jogger : buttonXp pressed
      Jogger : buttonXp released
      QEvent::MouseMove
      QEvent::MouseMove
      QEvent::MouseMove
      QEvent::MouseMove
      Jogger : buttonXp pressed
      Jogger : buttonXp released
      

      So moving off the button results in a released() and moving back on results in a pressed(). The move onto another button does not result in a pressed() for the new button.

      If I click somewhere that is not a button I see this:

      QEvent::MouseButtonPress
      QEvent::MouseButtonRelease
      

      I was surprised that I did not get the MouseButtonPress/MouseButtonRelease events for the buttons. I guess the pressed()/released() is handled first so the event() never occurs.

      I need to rebuild the code to run on my BeagleBone platform with the touchscreen. Hopefully it will output the TouchBegin/TouchUpdate/TouchEnd events. Not sure what I am going to be able to do with them but at least I have a path to look at...

      bigguinessB 1 Reply Last reply
      0
      • bigguinessB bigguiness

        @JoeCFD
        I tried adding the event() override to see if I could do something in it to handle the multi-touch event. Right now it's just a big switch() that outputs a qDebug() message for every event->type() so I can see what is happening. Once I verified it worked I started disabling the message for various events (Enter, Move, Leave, Paint, etc.) to filter out only the ones I am interested in.

        The output I am seeing now is not quite what I expected.

        My "jog" buttons are actually handled in a widget that I put on the dialog.

        namespace Ui {
        class Jogger;
        }
        
        class Jogger : public QWidget {
            Q_OBJECT
        public:
            // Constructor/Destructor
            // public methods
        protected:
            bool event(QEvent *event) override;
            ....
        };
        

        All the buttons are connected to the QPushButton::pressed() and QPushButton::released() signals using lambdas. I have added some qDebug() in each to debug the press/release.

        When I run code on a Windows machine (non-touchscreen) and use a mouse, I see debug like this when I press/release a button:

        Jogger : buttonXp pressed
        Jogger : buttonXp released
        

        I always get a press/release for a single button. If I click on a button and move the mouse off the button then back on the button then release, I see something like this:

        Jogger : buttonXp pressed
        Jogger : buttonXp released
        QEvent::MouseMove
        QEvent::MouseMove
        QEvent::MouseMove
        QEvent::MouseMove
        Jogger : buttonXp pressed
        Jogger : buttonXp released
        

        So moving off the button results in a released() and moving back on results in a pressed(). The move onto another button does not result in a pressed() for the new button.

        If I click somewhere that is not a button I see this:

        QEvent::MouseButtonPress
        QEvent::MouseButtonRelease
        

        I was surprised that I did not get the MouseButtonPress/MouseButtonRelease events for the buttons. I guess the pressed()/released() is handled first so the event() never occurs.

        I need to rebuild the code to run on my BeagleBone platform with the touchscreen. Hopefully it will output the TouchBegin/TouchUpdate/TouchEnd events. Not sure what I am going to be able to do with them but at least I have a path to look at...

        bigguinessB Offline
        bigguinessB Offline
        bigguiness
        wrote on last edited by
        #6

        OK this is confusing.

        If I touch and release a non-button location on the touchscreen I get:

        QEvent::MouseButtonPress
        QEvent::MouseButtonRelease
        

        If I touch and release two fingers to a non-button location I get:

        QEvent::MouseButtonPress
        QEvent::TouchUpdate
        Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
        Touch ID: 1 Pos: QPointF(xxx,xxx) Pressure: 0
        QEvent::TouchUpdate
        Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
        Touch ID: 1 Pos: QPointF(xxx,xxx) Pressure: 0
        QEvent::TouchUpdate
        Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
        QEvent::TouchEnd
        Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
        

        The last TouchUpdate and Touch may be Touch ID 0 or 1 depending on which finger is lifted first.

        If I touch and release one button I get:

        Jogger : buttonXX pressed
        Jogger : buttonXX released
        

        If I touch one button then another then release the second then the first I get:

        Jogger : buttonXX pressed
        Jogger : buttonXX released
        

        And if I touch one button then another then release the first then the second I get:

        Jogger : buttonXX pressed
        

        So, I do get the multi-touch events as long as I don't touch a button. But touching a button does not give me any events. And it they are not released in the correct order, I don't get the final release.

        Any other ideas?

        JoeCFDJ 1 Reply Last reply
        0
        • bigguinessB bigguiness

          OK this is confusing.

          If I touch and release a non-button location on the touchscreen I get:

          QEvent::MouseButtonPress
          QEvent::MouseButtonRelease
          

          If I touch and release two fingers to a non-button location I get:

          QEvent::MouseButtonPress
          QEvent::TouchUpdate
          Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
          Touch ID: 1 Pos: QPointF(xxx,xxx) Pressure: 0
          QEvent::TouchUpdate
          Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
          Touch ID: 1 Pos: QPointF(xxx,xxx) Pressure: 0
          QEvent::TouchUpdate
          Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
          QEvent::TouchEnd
          Touch ID: 0 Pos: QPointF(xxx,xxx) Pressure: 0
          

          The last TouchUpdate and Touch may be Touch ID 0 or 1 depending on which finger is lifted first.

          If I touch and release one button I get:

          Jogger : buttonXX pressed
          Jogger : buttonXX released
          

          If I touch one button then another then release the second then the first I get:

          Jogger : buttonXX pressed
          Jogger : buttonXX released
          

          And if I touch one button then another then release the first then the second I get:

          Jogger : buttonXX pressed
          

          So, I do get the multi-touch events as long as I don't touch a button. But touching a button does not give me any events. And it they are not released in the correct order, I don't get the final release.

          Any other ideas?

          JoeCFDJ Offline
          JoeCFDJ Offline
          JoeCFD
          wrote on last edited by JoeCFD
          #7

          @bigguiness It could be the case that touch events are converted to pressed and released events only when a button is clicked.

          Can you try one more thing:
          To receive touch events, widgets have to have the Qt::WA_AcceptTouchEvents attribute set and graphics items need to have the acceptTouchEvents attribute set to true.
          to see if you are able to get more.

          bigguinessB 1 Reply Last reply
          0
          • JoeCFDJ JoeCFD

            @bigguiness It could be the case that touch events are converted to pressed and released events only when a button is clicked.

            Can you try one more thing:
            To receive touch events, widgets have to have the Qt::WA_AcceptTouchEvents attribute set and graphics items need to have the acceptTouchEvents attribute set to true.
            to see if you are able to get more.

            bigguinessB Offline
            bigguinessB Offline
            bigguiness
            wrote on last edited by
            #8

            @JoeCFD setting the Qt::WA_AcceptTouchEvents attribute on all the buttons did not change anything.

            Do i also need to set it on the Jogger widget itself? This is my Jogger widget:
            Jogger.png

            Also, I just noticed that the second touch does not have to be on a button. If any location in the widget is touched while a button is touched, if the button is released before the second touch I don't get the release. But, if the second location is released first I do get the release of the button.

            bigguinessB 1 Reply Last reply
            0
            • bigguinessB bigguiness

              @JoeCFD setting the Qt::WA_AcceptTouchEvents attribute on all the buttons did not change anything.

              Do i also need to set it on the Jogger widget itself? This is my Jogger widget:
              Jogger.png

              Also, I just noticed that the second touch does not have to be on a button. If any location in the widget is touched while a button is touched, if the button is released before the second touch I don't get the release. But, if the second location is released first I do get the release of the button.

              bigguinessB Offline
              bigguinessB Offline
              bigguiness
              wrote on last edited by
              #9

              I tried setting the Qt::WA_AcceptTouchEvents attribute on the Jogger widget itself.

              Now ALL button touches show up as TouchBegin/TouchUpdate/TouchEnd events. I never get a pressed() or released() signal.

              bigguinessB 1 Reply Last reply
              0
              • bigguinessB bigguiness

                I tried setting the Qt::WA_AcceptTouchEvents attribute on the Jogger widget itself.

                Now ALL button touches show up as TouchBegin/TouchUpdate/TouchEnd events. I never get a pressed() or released() signal.

                bigguinessB Offline
                bigguinessB Offline
                bigguiness
                wrote on last edited by
                #10

                OK. The Qt::WA_AcceptTouchEvents attribute on the Jogger widget might work. I'm just not sure how to do the following.

                1. I'm only interested in the first touch, so ignore all touchPoint.id() != 0.
                2. A QEvent::TouchBegin event is basically a QEvent::MouseButtonPress.
                3. A QEvent::TouchEnd is basically a QEvent::MouseButtonRelease.

                So:

                protected:
                    bool event(QEvent *event) override {
                        if (event->type() == QEvent::TouchBegin) {
                            QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
                
                            foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints()) {
                                if (touchPoint.id() == 0) {
                                    // figure out what button is associated with the touchPoint.pos()
                                    // emit pressed() for that button
                                }
                            }
                            return true; // handled as a QEvent::MouseButtonPress
                        } else if (event->type() == QEvent::TouchUpdate) {
                            return true; // ignore these
                        } else if (event->type() == QEvent::TouchEnd) {
                            QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
                
                            foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints()) {
                                if (touchPoint.id() == 0) {
                                    // figure out what button is associated with the touchPoint.pos()
                                    // emit released() for that button
                                }
                            }
                            return true; // handled as a QEvent::MouseButtonRelease
                        }
                        return QWidget::event(event);
                    }
                

                This may work I just don't know how to work out the button based on the touchPoint.pos(). I assume after that I can just do a "emit button->pressed()/released()".

                What do you think?

                JoeCFDJ 1 Reply Last reply
                0
                • bigguinessB bigguiness

                  OK. The Qt::WA_AcceptTouchEvents attribute on the Jogger widget might work. I'm just not sure how to do the following.

                  1. I'm only interested in the first touch, so ignore all touchPoint.id() != 0.
                  2. A QEvent::TouchBegin event is basically a QEvent::MouseButtonPress.
                  3. A QEvent::TouchEnd is basically a QEvent::MouseButtonRelease.

                  So:

                  protected:
                      bool event(QEvent *event) override {
                          if (event->type() == QEvent::TouchBegin) {
                              QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
                  
                              foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints()) {
                                  if (touchPoint.id() == 0) {
                                      // figure out what button is associated with the touchPoint.pos()
                                      // emit pressed() for that button
                                  }
                              }
                              return true; // handled as a QEvent::MouseButtonPress
                          } else if (event->type() == QEvent::TouchUpdate) {
                              return true; // ignore these
                          } else if (event->type() == QEvent::TouchEnd) {
                              QTouchEvent *touchEvent = static_cast<QTouchEvent*>(event);
                  
                              foreach (const QTouchEvent::TouchPoint &touchPoint, touchEvent->touchPoints()) {
                                  if (touchPoint.id() == 0) {
                                      // figure out what button is associated with the touchPoint.pos()
                                      // emit released() for that button
                                  }
                              }
                              return true; // handled as a QEvent::MouseButtonRelease
                          }
                          return QWidget::event(event);
                      }
                  

                  This may work I just don't know how to work out the button based on the touchPoint.pos(). I assume after that I can just do a "emit button->pressed()/released()".

                  What do you think?

                  JoeCFDJ Offline
                  JoeCFDJ Offline
                  JoeCFD
                  wrote on last edited by
                  #11

                  @bigguiness if touch events come, you can get touch points from
                  https://doc.qt.io/qt-5.15/qtouchevent.html#touchPoints
                  const QListQTouchEvent::TouchPoint &QTouchEvent::touchPoints() const
                  Then follow the code of @johngod.

                  bigguinessB 1 Reply Last reply
                  0
                  • JoeCFDJ JoeCFD

                    @bigguiness if touch events come, you can get touch points from
                    https://doc.qt.io/qt-5.15/qtouchevent.html#touchPoints
                    const QListQTouchEvent::TouchPoint &QTouchEvent::touchPoints() const
                    Then follow the code of @johngod.

                    bigguinessB Offline
                    bigguinessB Offline
                    bigguiness
                    wrote on last edited by
                    #12

                    @JoeCFD I have the touch points already.

                    How do I figure out what button is associated with the point so I can then emit the pressed() or released() signal for that button.

                    JoeCFDJ 1 Reply Last reply
                    0
                    • bigguinessB bigguiness

                      @JoeCFD I have the touch points already.

                      How do I figure out what button is associated with the point so I can then emit the pressed() or released() signal for that button.

                      JoeCFDJ Offline
                      JoeCFDJ Offline
                      JoeCFD
                      wrote on last edited by JoeCFD
                      #13

                      @bigguiness check if these points are inside rect of the buttons.
                      https://doc.qt.io/qt-5.15/qrect.html#contains

                      1 Reply Last reply
                      0
                      • bigguinessB Offline
                        bigguinessB Offline
                        bigguiness
                        wrote on last edited by
                        #14

                        @JoeCFD thanks for the leads.

                        I have it working now using event() to handle the touch events instead of using the normal mouse events.

                        A couple notes about this.

                        1. Setting the Qt::WA_AcceptTouchEvents attribute disables all the normal moue events.

                        Instead of the mousePressEvent() -> emit pressed() happening, you get an event() with either a QEvent::TouchBegin or QEvent::TouchUpdate. You then have to figure out what button the touch points are associated with. Then you need to handle the "pressed" and setDown(true) the button.

                        As long as any touch is still present you will periodically get an event() with QEvent::TouchUpdate. This also happens instead of a mouseMoveEvent(). Only the touches still active will be in the touch points. If a touch you are interested in is not in the points, that associated button will need to be "released" and setDown(false).

                        Instead of a mouseReleaseEvent() -> emit released(), when all touches are released you will get an event() with QEvent::TouchEnd with the touch points of the final released touches. Again these need to be associated to buttons that need to be "released" and setDown(false).

                        In my case I'm only interested in the first touch so I ignore all QTouchEvent::TouchPoint id() != 0.

                        This seems to be something that Qt should be able to handle internally. But.... Oh well...

                        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