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. How to receive mouse events for QDoubleSpinBox

How to receive mouse events for QDoubleSpinBox

Scheduled Pinned Locked Moved Solved General and Desktop
23 Posts 8 Posters 3.8k 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.
  • dheerendraD Offline
    dheerendraD Offline
    dheerendra
    Qt Champions 2022
    wrote on last edited by
    #8

    @shreya_agrawal - No direct way without overriding appropriate mouseEvent methods. As work-around you can check the change in value. You can decide up or down based on value increment/decrement.

    Dheerendra
    @Community Service
    Certified Qt Specialist
    http://www.pthinks.com

    S 1 Reply Last reply
    0
    • S shreya_agrawal

      Hello!
      Is there any way to get get the click events of the up and down buttons separately in the spin box?

      Pl45m4P Offline
      Pl45m4P Offline
      Pl45m4
      wrote on last edited by
      #9

      @shreya_agrawal

      You could use the valueChanged signal and check if the new value is higher or lower than the old one. Then you know what button what possibly clicked... (or what value was added via typing, if you can live with that)


      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

      ~E. W. Dijkstra

      1 Reply Last reply
      0
      • dheerendraD dheerendra

        @shreya_agrawal - No direct way without overriding appropriate mouseEvent methods. As work-around you can check the change in value. You can decide up or down based on value increment/decrement.

        S Offline
        S Offline
        shreya_agrawal
        wrote on last edited by
        #10

        @dheerendra
        Thank you for your reply !
        Are you aware of any mouse events which can be used for this, so I don't have to use the valueChanged signal?
        I did find a workaround by using rectangles inside the spin box to distinguish between up and down buttons, but I don't think this is the most accurate approach.

        JonBJ 1 Reply Last reply
        0
        • S shreya_agrawal

          @dheerendra
          Thank you for your reply !
          Are you aware of any mouse events which can be used for this, so I don't have to use the valueChanged signal?
          I did find a workaround by using rectangles inside the spin box to distinguish between up and down buttons, but I don't think this is the most accurate approach.

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

          @shreya_agrawal
          Have you investigated something based on:

          for (QWidget *child: spinBox.findChildren<QWidget *>())
              child->installEventFilter(this);
          

          I am not sure whether the buttons you want are widgets or (as may well be the case) simply drawn as part of the style. The above will at least show where actual widgets are.

          S 1 Reply Last reply
          0
          • JonBJ JonB

            @shreya_agrawal
            Have you investigated something based on:

            for (QWidget *child: spinBox.findChildren<QWidget *>())
                child->installEventFilter(this);
            

            I am not sure whether the buttons you want are widgets or (as may well be the case) simply drawn as part of the style. The above will at least show where actual widgets are.

            S Offline
            S Offline
            shreya_agrawal
            wrote on last edited by
            #12

            @JonB
            Thank you for your reply!
            Actually the only child the spin box returns is its line edit, not the up and down buttons.

            JonBJ 1 Reply Last reply
            0
            • S shreya_agrawal

              @JonB
              Thank you for your reply!
              Actually the only child the spin box returns is its line edit, not the up and down buttons.

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

              @shreya_agrawal
              Yes, I think I read that. Sadly it means the arrows are just drawn as part of the style, they are not widgets you can connect to. Which should mean click is recognised by coordinates internally in spinbox code. Not what you wanted. You might examine Qt source code if you really need to know how it does it. It does sound as though working on valueChanged(), which the internal code must resolve via mouse position relative to arrow drawing, would be the simplest "high level" approach if you want to avoid duplicating internal coordinate calculation.

              S 1 Reply Last reply
              1
              • JonBJ JonB

                @shreya_agrawal
                Yes, I think I read that. Sadly it means the arrows are just drawn as part of the style, they are not widgets you can connect to. Which should mean click is recognised by coordinates internally in spinbox code. Not what you wanted. You might examine Qt source code if you really need to know how it does it. It does sound as though working on valueChanged(), which the internal code must resolve via mouse position relative to arrow drawing, would be the simplest "high level" approach if you want to avoid duplicating internal coordinate calculation.

                S Offline
                S Offline
                shreya_agrawal
                wrote on last edited by
                #14

                @JonB
                Okay, I will look into it further and post if I reach somewhere.

                JonBJ 2 Replies Last reply
                0
                • Christian EhrlicherC Offline
                  Christian EhrlicherC Offline
                  Christian Ehrlicher
                  Lifetime Qt Champion
                  wrote on last edited by
                  #15

                  override mousePressEvent and get the positions of the spinboxes through the style with subElementRect() - this is what QAbstractSpinBox is doing

                  Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                  Visit the Qt Academy at https://academy.qt.io/catalog

                  JonBJ 1 Reply Last reply
                  4
                  • S shreya_agrawal

                    @JonB
                    Okay, I will look into it further and post if I reach somewhere.

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

                    @shreya_agrawal
                    I've had a look at the on-line source (I don't have source files myself). Although I haven't gone all the way the through, the gist seems to be that Qt notes whether you mouse down on what it maintains as an internal "hover control", which will be the up arrow, down arrow or nothing.

                    The relevant functions are https://codebrowser.dev/qt6/qtbase/src/widgets/widgets/qabstractspinbox.cpp.html#_ZN16QAbstractSpinBox15mousePressEventEP11QMouseEvent

                    void QAbstractSpinBox::mousePressEvent(QMouseEvent *event)
                    {
                        Q_D(QAbstractSpinBox);
                        d->keyboardModifiers = event->modifiers();
                        if (event->button() != Qt::LeftButton || d->buttonState != None) {
                            return;
                        }
                        d->updateHoverControl(event->position().toPoint());
                        event->accept();
                        const StepEnabled se = (d->buttonSymbols == NoButtons) ? StepEnabled(StepNone) : stepEnabled();
                        if ((se & StepUpEnabled) && d->hoverControl == QStyle::SC_SpinBoxUp) {
                            d->updateState(true);
                        } else if ((se & StepDownEnabled) && d->hoverControl == QStyle::SC_SpinBoxDown) {
                            d->updateState(false);
                        } else {
                            event->ignore();
                        }
                    }
                    

                    and the call to d->updateHoverControl(event->position().toPoint()); https://codebrowser.dev/qt6/qtbase/src/widgets/widgets/qabstractspinbox.cpp.html#_ZN23QAbstractSpinBoxPrivate18updateHoverControlERK6QPoint

                    /*!
                        \internal
                        Updates the old and new hover control. Does nothing if the hover
                        control has not changed.
                    */
                    bool QAbstractSpinBoxPrivate::updateHoverControl(const QPoint &pos)
                    {
                        Q_Q(QAbstractSpinBox);
                        QRect lastHoverRect = hoverRect;
                        QStyle::SubControl lastHoverControl = hoverControl;
                        bool doesHover = q->testAttribute(Qt::WA_Hover);
                        if (lastHoverControl != newHoverControl(pos) && doesHover) {
                            q->update(lastHoverRect);
                            q->update(hoverRect);
                            return true;
                        }
                        return !doesHover;
                    }
                    /*!
                        \internal
                        Returns the hover control at \a pos.
                        This will update the hoverRect and hoverControl.
                    */
                    QStyle::SubControl QAbstractSpinBoxPrivate::newHoverControl(const QPoint &pos)
                    {
                        Q_Q(QAbstractSpinBox);
                        QStyleOptionSpinBox opt;
                        q->initStyleOption(&opt);
                        opt.subControls = QStyle::SC_All;
                        hoverControl = q->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, pos, q);
                        hoverRect = q->style()->subControlRect(QStyle::CC_SpinBox, &opt, hoverControl, q);
                        return hoverControl;
                    }
                    

                    So ultimately I think it relies on

                        hoverControl = q->style()->hitTestComplexControl(QStyle::CC_SpinBox, &opt, pos, q);
                        hoverRect = q->style()->subControlRect(QStyle::CC_SpinBox, &opt, hoverControl, q);
                    

                    to find the location of the arrow buttons. And https://codebrowser.dev/qt6/qtbase/src/widgets/widgets/qabstractspinbox.cpp.html#_ZNK16QAbstractSpinBox15initStyleOptionEP19QStyleOptionSpinBox includes

                        if (d->buttonSymbols != QAbstractSpinBox::NoButtons) {
                            option->subControls |= QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown;
                            if (d->buttonState & Up) {
                                option->activeSubControls = QStyle::SC_SpinBoxUp;
                            } else if (d->buttonState & Down) {
                                option->activeSubControls = QStyle::SC_SpinBoxDown;
                            }
                    

                    so this is to do with recognising which button ultimately.

                    So like I said unless you want to replicate this (see QStyle for some of the calls) it would be easier for you to react to the generated valueChanged() signal.

                    1 Reply Last reply
                    3
                    • Christian EhrlicherC Christian Ehrlicher

                      override mousePressEvent and get the positions of the spinboxes through the style with subElementRect() - this is what QAbstractSpinBox is doing

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

                      @Christian-Ehrlicher said in How to receive mouse events for QDoubleSpinBox:

                      override mousePressEvent and get the positions of the spinboxes through the style with subElementRect() - this is what QAbstractSpinBox is doing

                      Ooohh, you posted this while I was doing all my source code searching! Not sure how your subElementRect() relates to the subControlRect() I have come across in the code above.

                      1 Reply Last reply
                      0
                      • S shreya_agrawal

                        @JonB
                        Okay, I will look into it further and post if I reach somewhere.

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

                        @shreya_agrawal
                        Ah ha! I little Googling leads me to QSpinbox Check if up or down button is pressed which seems to give the relatively simple code

                        class SpinBox(QSpinBox):
                            upClicked = pyqtSignal()
                            downClicked = pyqtSignal()
                        
                            def mousePressEvent(self, event):
                                super().mousePressEvent(event)
                        
                                opt = QStyleOptionSpinBox()
                                self.initStyleOption(opt)
                        
                                control = self.style().hitTestComplexControl(
                                    QStyle.CC_SpinBox, opt, event.pos(), self
                                )
                                if control == QStyle.SC_SpinBoxUp:
                                    self.upClicked.emit()
                                elif control == QStyle.SC_SpinBoxDown:
                                    self.downClicked.emit()
                        

                        @eyllanesc's answers & code are usually good, so it may be this simple.

                        S 1 Reply Last reply
                        2
                        • JonBJ JonB

                          @shreya_agrawal
                          Ah ha! I little Googling leads me to QSpinbox Check if up or down button is pressed which seems to give the relatively simple code

                          class SpinBox(QSpinBox):
                              upClicked = pyqtSignal()
                              downClicked = pyqtSignal()
                          
                              def mousePressEvent(self, event):
                                  super().mousePressEvent(event)
                          
                                  opt = QStyleOptionSpinBox()
                                  self.initStyleOption(opt)
                          
                                  control = self.style().hitTestComplexControl(
                                      QStyle.CC_SpinBox, opt, event.pos(), self
                                  )
                                  if control == QStyle.SC_SpinBoxUp:
                                      self.upClicked.emit()
                                  elif control == QStyle.SC_SpinBoxDown:
                                      self.downClicked.emit()
                          

                          @eyllanesc's answers & code are usually good, so it may be this simple.

                          S Offline
                          S Offline
                          shreya_agrawal
                          wrote on last edited by shreya_agrawal
                          #19

                          @JonB
                          Well thank you for sparing so much of your time!
                          Sadly, the Qt version I am using does not support the use of SC_SpinBoxUp and SC_SpinBoxDown subcontrols :(
                          I think I will have to rely on the valueChanged() signal for now.

                          JonBJ 1 Reply Last reply
                          0
                          • S shreya_agrawal

                            @JonB
                            Well thank you for sparing so much of your time!
                            Sadly, the Qt version I am using does not support the use of SC_SpinBoxUp and SC_SpinBoxDown subcontrols :(
                            I think I will have to rely on the valueChanged() signal for now.

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

                            @shreya_agrawal said in How to receive mouse events for QDoubleSpinBox:

                            Sadly, the Qt version I am using does not support the use of SC_SpinBoxUp and SC_SpinBoxDown subcontrols :(

                            Pardon? State your exact Qt version. Since it is available in Qt4, 5, 6 I doubt your statement.
                            Show the code you have tried and the error message you get. Don't forget that Python's QStyle.SC_SpinBoxUp is C++'s QStyle::SC_SpinBoxUp....

                            S 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @shreya_agrawal said in How to receive mouse events for QDoubleSpinBox:

                              Sadly, the Qt version I am using does not support the use of SC_SpinBoxUp and SC_SpinBoxDown subcontrols :(

                              Pardon? State your exact Qt version. Since it is available in Qt4, 5, 6 I doubt your statement.
                              Show the code you have tried and the error message you get. Don't forget that Python's QStyle.SC_SpinBoxUp is C++'s QStyle::SC_SpinBoxUp....

                              S Offline
                              S Offline
                              shreya_agrawal
                              wrote on last edited by
                              #21

                              @JonB
                              Qt Version: Qt Creator 4.12.2 Based on Qt 5.14.2 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit)

                              Line of code: QRect downButtonRect = spinBox->style()->subElementRect(QStyle::SE_SpinBoxDown, spinBox);

                              Error Message: no member named 'SE_SpinBoxDown' in 'QStyle'

                              JonBJ 1 Reply Last reply
                              0
                              • S shreya_agrawal

                                @JonB
                                Qt Version: Qt Creator 4.12.2 Based on Qt 5.14.2 (GCC 5.3.1 20160406 (Red Hat 5.3.1-6), 64 bit)

                                Line of code: QRect downButtonRect = spinBox->style()->subElementRect(QStyle::SE_SpinBoxDown, spinBox);

                                Error Message: no member named 'SE_SpinBoxDown' in 'QStyle'

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

                                @shreya_agrawal
                                Why don't you copy from both the original code and what I wrote, instead of typing it on yourself and as we can see getting it wrong/misspelt...? That's why copy & paste exists.

                                S 1 Reply Last reply
                                0
                                • JonBJ JonB

                                  @shreya_agrawal
                                  Why don't you copy from both the original code and what I wrote, instead of typing it on yourself and as we can see getting it wrong/misspelt...? That's why copy & paste exists.

                                  S Offline
                                  S Offline
                                  shreya_agrawal
                                  wrote on last edited by
                                  #23

                                  @JonB
                                  Oops! My Bad :)
                                  The solution worked. Thank you for your patience.

                                  1 Reply Last reply
                                  1

                                  • Login

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