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. QPushButton, Overwrite and StyleSheet
QtWS25 Last Chance

QPushButton, Overwrite and StyleSheet

Scheduled Pinned Locked Moved Solved General and Desktop
qpushbuttonqstylesheetmousepressevent
5 Posts 3 Posters 4.6k 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.
  • J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by
    #1

    Hi, everyone,

    I have a QPushButton subclass cButton. I did that to add a new state for the StyleSheet and to forward mouse events to the parent widget.

    Seems simple enough:

    class cButton: public QPushButton
    {
        Q_OBJECT
        Q_PROPERTY(bool connected READ isConnected WRITE changeConnected)
    public:
        explicit cButton(QWidget *parent = 0): QPushButton(parent){}
        ~cButton(){}
        bool isConnected(){return connected;}
    
    public slots:
        void changeConnected(bool state){
            connected = state;
            style()->unpolish(this);
            style()->polish(this);
        }
    signals:
        void signalPressedEvent(QMouseEvent *e);
        void signalReleaseEvent(QMouseEvent *e);
    protected:
        bool connected = false;
        QPoint m_Origin;
    
        virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
            m_Origin = mapToGlobal(e->pos());
            emit signalPressedEvent(e);
            emit pressed();
        }
        virtual void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
            QPoint m_Dest = mapToGlobal(e->pos());
            emit signalReleaseEvent(e);
            if(abs(m_Dest.x()-m_Origin.x()) < this->width()/4 && abs(m_Dest.y()-m_Origin.y())<this->height()/4){
                emit released();
                emit clicked();
            }
        }
    };
    

    The problem is, the StyleSheet does not recognize the pressed state anymore.
    QPushButton:pressed{ //do Stuff} has no effect .
    QPushButton[connected = true]{//doStuff} works fine, so I could replace pressed with an other custom property, but I'm wondering, if there's an other way.

    I can't change the mousePressEvent function to this:

    virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
            m_Origin = mapToGlobal(e->pos());
            emit signalPressedEvent(e);
            QPushButton::mousePressEvent(e);
        }
    

    It would enable the StyleSheet part, but than signalPressedEvent(e) would not be forwarded to the parent.


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

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

      Hi,

      Out of curiosity, why do you need to "forward" that event to the parent widget like that ?

      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
      • Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by Chris Kawa
        #3

        You should call the base implementation. Doing otherwise is just a bug lurking to be uncovered when least expected. Also passing an event pointer via a signal is a bad idea. You're not in control of how someone connects to it, and if the connection is in any way deferred (i.e. to another thread or via queued connection) the pointer will be invalid, and that's another hard to track bug for the future.
        Events are not meant to be moved around via signals. If you want to pass an event to a parent you can always create a new event (by copying the one you got) and use sendEvent. That's yet another unusual thing to do though. Are you sure you need the signals to pass the event pointer? Wouldn't it be enough to pass any event data that you need (e.g. the cursor position or mouse buttons)?

        J.HilkJ 1 Reply Last reply
        2
        • J.HilkJ Offline
          J.HilkJ Offline
          J.Hilk
          Moderators
          wrote on last edited by
          #4

          Hi,
          So I totally missed that someone answered. Sorry about that.

          To answer some questions:

          @SGaist said in QPushButton, Overwrite and StyleSheet:

          Hi,

          Out of curiosity, why do you need to "forward" that event to the parent widget like that ?

          I have a custom widget that manages a series of buttons, labels and animations. <- That is working fine.

          Now was the idea to allow the user to "grab" the widget and move it around. To realize that, I need to catch when a mousebutton is pressed and the mose is moved. To calculate the new position.
          I overwrote the QMouseEvents in the main custom Widget to get this information. But whenever I lclick on a QPushButton, no Signal is passed to the main widget.

          @Chris-Kawa said in QPushButton, Overwrite and StyleSheet:

          Events are not meant to be moved around via signals. If you want to pass an event to a parent you can always create a new event (by copying the one you got) and use sendEvent. That's yet another unusual thing to do though. Are you sure you need the signals to pass the event pointer? Wouldn't it be enough to pass any event data that you need (e.g. the cursor position or mouse buttons)>

          A good point, I only need the pos() and the QMouseEvent::Type, I'll change that later for sure.

          So, over the weekend, I managed to find a solution. However, I'm not sure why I have to do shedule the signal into the next eventloop cycle.

          This way I get the Signal in my other class:

          virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
                  m_Origin = mapToGlobal(e->pos());
                  QTimer::singleShot(0,this,[=]{emit signalMouseEvent(e);});
                  QPushButton::mousePressEvent(e);
              }
          

          This way I don't get the Signal:

          virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
                  m_Origin = mapToGlobal(e->pos());
                  emit signalMouseEvent(e);
                  QPushButton::mousePressEvent(e);
              }
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          1 Reply Last reply
          0
          • Chris KawaC Chris Kawa

            You should call the base implementation. Doing otherwise is just a bug lurking to be uncovered when least expected. Also passing an event pointer via a signal is a bad idea. You're not in control of how someone connects to it, and if the connection is in any way deferred (i.e. to another thread or via queued connection) the pointer will be invalid, and that's another hard to track bug for the future.
            Events are not meant to be moved around via signals. If you want to pass an event to a parent you can always create a new event (by copying the one you got) and use sendEvent. That's yet another unusual thing to do though. Are you sure you need the signals to pass the event pointer? Wouldn't it be enough to pass any event data that you need (e.g. the cursor position or mouse buttons)?

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #5

            @Chris-Kawa turns out, you were spot on! I had some difficulties to compile my "fix" in release configuration.
            So I went and rewrote the class, with your comment in mind. I intoduced a new signal and changed the overrides accordingly.

            void signalEvent(QMouseEvent::Type t, QPoint p);
            

            now, I don't need the timer, it also works in debug as well as in release mode...

            virtual void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE{
                    emit signalEvent(QMouseEvent::MouseButtonPress, e->pos());
                    QPushButton::mousePressEvent(e);
                }
            

            works like a charm. Thanks!


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            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