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. QObject::setProperty() signalling solution?
Forum Updated to NodeBB v4.3 + New Features

QObject::setProperty() signalling solution?

Scheduled Pinned Locked Moved Solved General and Desktop
16 Posts 3 Posters 4.9k Views 1 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.
  • VRoninV Offline
    VRoninV Offline
    VRonin
    wrote on last edited by VRonin
    #7

    I would subclass QWidget (sorry for C++):

    class PolishedWidget : public QWidget {
        Q_OBJECT
        Q_DISABLE_COPY(PolishedWidget)
    public:
        explicit PolishedWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags())
            : QWidget(parent, f)
        {}
    protected:
        bool event(QEvent* event) Q_DECL_OVERRIDE
        {
            if (event->type() == QEvent::DynamicPropertyChange) {
                style()->unpolish(this);
                style()->polish(this);
            }
            return QWidget::event(event);
        }
    };
    

    Now all you need to do is change your other widgets to inherit from PolishedWidget rather than QWidget

    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
    ~Napoleon Bonaparte

    On a crusade to banish setIndexWidget() from the holy land of Qt

    JonBJ 1 Reply Last reply
    2
    • VRoninV VRonin

      I would subclass QWidget (sorry for C++):

      class PolishedWidget : public QWidget {
          Q_OBJECT
          Q_DISABLE_COPY(PolishedWidget)
      public:
          explicit PolishedWidget(QWidget* parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags())
              : QWidget(parent, f)
          {}
      protected:
          bool event(QEvent* event) Q_DECL_OVERRIDE
          {
              if (event->type() == QEvent::DynamicPropertyChange) {
                  style()->unpolish(this);
                  style()->polish(this);
              }
              return QWidget::event(event);
          }
      };
      

      Now all you need to do is change your other widgets to inherit from PolishedWidget rather than QWidget

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

      @VRonin
      No, of course I would do this if I could!! :)

      I'm not defining my own widgets derived from QWidget. I'm using all the various Qt widgets, QLineEdit, QPushButton, etc., etc. They all of course already derive from QWidget, I'd like them to have derived from PolishedWidget but they don't!

      I'm saying I have gone through code and made it so I always create my own wrapper classes, one for each Qt widget class I use (like MyLineEdit just deriving from QLineEdit). So we have the luxury of a derived class for each widget class to put our code in. So we can do either:

      • The way above, filtering the event, in each derived class's definition. Outside world will call myLine.setProperty("class", ...).

      • In each derived class's definition, supply a method, like setProperty() or setPropertyClass() or whatever, which includes calling polish() code itself (no event filtering). Outside world will call myLine.setPropertyClass(...).

      Do we prefer one approach over the other?

      1 Reply Last reply
      0
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #9

        Do we prefer one approach over the other?

        I do prefer the first option but I wouldn't subclass every single Qt Class.

        In C++ You have 2 options (I'm 100% sure the second one is available to python too):

        template <class T>
        class PolishedWidget : public T{
        public:
            explicit PolishedWidget(QWidget* parent = Q_NULLPTR)
                : T(parent, f)
            {}
        protected:
            bool event(QEvent* event) Q_DECL_OVERRIDE
            {
                if (event->type() == QEvent::DynamicPropertyChange) {
                    style()->unpolish(this);
                    style()->polish(this);
                }
                return T::event(event);
            }
        };
        

        Now you can create PolishedWidget<QLineEdit> myLine; and PolishedWidget<QPushButton> myButton;


        Install an event filter:

        class Polisher : public QObject {
            Q_OBJECT
            Q_DISABLE_COPY(Polisher)
        public:
            Polisher(QObject* parent = Q_NULLPTR)
                : QObject(parent)
            { }
        protected:
            bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE
            {
                if (event->type() == QEvent::DynamicPropertyChange) {
                    QWidget* objWidget = qobject_cast<QWidget*>(obj);
                    if (objWidget) {
                        objWidget->style()->unpolish(objWidget);
                        objWidget->style()->polish(objWidget);
                    }
                }
                return QObject::eventFilter(obj, event);
            }
        };
        

        Now you can use:

        Polisher* polisher = new Polisher(parent);
        QLineEdit* myLine =new QLineEdit(parent);
        QPushButton* myButton=new QPushButton(parent);
        myLine ->setEventFilter(polisher);
        myButton->setEventFilter(polisher);
        

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        JonBJ 1 Reply Last reply
        1
        • VRoninV VRonin

          Do we prefer one approach over the other?

          I do prefer the first option but I wouldn't subclass every single Qt Class.

          In C++ You have 2 options (I'm 100% sure the second one is available to python too):

          template <class T>
          class PolishedWidget : public T{
          public:
              explicit PolishedWidget(QWidget* parent = Q_NULLPTR)
                  : T(parent, f)
              {}
          protected:
              bool event(QEvent* event) Q_DECL_OVERRIDE
              {
                  if (event->type() == QEvent::DynamicPropertyChange) {
                      style()->unpolish(this);
                      style()->polish(this);
                  }
                  return T::event(event);
              }
          };
          

          Now you can create PolishedWidget<QLineEdit> myLine; and PolishedWidget<QPushButton> myButton;


          Install an event filter:

          class Polisher : public QObject {
              Q_OBJECT
              Q_DISABLE_COPY(Polisher)
          public:
              Polisher(QObject* parent = Q_NULLPTR)
                  : QObject(parent)
              { }
          protected:
              bool eventFilter(QObject* obj, QEvent* event) Q_DECL_OVERRIDE
              {
                  if (event->type() == QEvent::DynamicPropertyChange) {
                      QWidget* objWidget = qobject_cast<QWidget*>(obj);
                      if (objWidget) {
                          objWidget->style()->unpolish(objWidget);
                          objWidget->style()->polish(objWidget);
                      }
                  }
                  return QObject::eventFilter(obj, event);
              }
          };
          

          Now you can use:

          Polisher* polisher = new Polisher(parent);
          QLineEdit* myLine =new QLineEdit(parent);
          QPushButton* myButton=new QPushButton(parent);
          myLine ->setEventFilter(polisher);
          myButton->setEventFilter(polisher);
          
          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #10

          @VRonin
          For #1: Yeah, now the question is I wonder how/whether I'm supposed to do template class in Python/PyQt... !

          However, the point is you prefer event filter approach over explicit "set-property-with-call-to-polish" method. I'll go down that route.

          For #2: I don't want to have to insert a line of a code to setEventFilter after each of thousands of lines of existing code, wherever any widget is created. Not to remember to do it in the future. Since I am now in a position where every QLineEdit or QPushButon is already a JLineEdit or JPushButon [code only uses, say, 10 Qt widget types, so that's the sub-classing I've done], I can move the polishing code into its event filter and not insert loads of lines across loads of files.

          VRoninV 1 Reply Last reply
          0
          • JonBJ JonB

            @VRonin
            For #1: Yeah, now the question is I wonder how/whether I'm supposed to do template class in Python/PyQt... !

            However, the point is you prefer event filter approach over explicit "set-property-with-call-to-polish" method. I'll go down that route.

            For #2: I don't want to have to insert a line of a code to setEventFilter after each of thousands of lines of existing code, wherever any widget is created. Not to remember to do it in the future. Since I am now in a position where every QLineEdit or QPushButon is already a JLineEdit or JPushButon [code only uses, say, 10 Qt widget types, so that's the sub-classing I've done], I can move the polishing code into its event filter and not insert loads of lines across loads of files.

            VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by VRonin
            #11

            @JonB said in QObject::setProperty() signalling solution?:

            now the question is I wonder how/whether I'm supposed to do template class in Python/PyQt

            How: https://docs.python.org/3.6/library/typing.html#user-defined-generic-types
            Whether: give it a try, and see if it works

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            JonBJ 1 Reply Last reply
            2
            • VRoninV VRonin

              @JonB said in QObject::setProperty() signalling solution?:

              now the question is I wonder how/whether I'm supposed to do template class in Python/PyQt

              How: https://docs.python.org/3.6/library/typing.html#user-defined-generic-types
              Whether: give it a try, and see if it works

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

              @VRonin
              I have made the change (in my own way!) so that the widgets I use have an event filter on dynamic property changes to cause required polishing. I examine QDynamicPropertyChangeEvent::propertyName() and do so only if it's one of mine (like class). There are other cases too (e.g. I make setting/clearing read-only affect line edit's background color).

              How expensive do you think polish/unpolish() (or for that matter re-assigning setStyleSheet() if I chose to do it that way) are?

              The approach we have chosen re-polishes every time I set some "property". However, somewhere in the docs it states we only need to do this when we change a property on something like an already-displayed widget.

              Thus, if I set properties immediately after widget construction --- as I may well do --- I will do re-polishes for each one, even though none of them are necessary. OTOH, if I want to change the properties at a later date after widget has been shown, I would indeed need the re-polishing, but only then.

              I haven't found all the circumstances, but I'm wondering whether my event filter could test something like QWidget::isVisible() before doing the re-polish, so that it does not do it when unnecessarily early in the widget's life-cycle. Any opinion/comment?

              VRoninV 1 Reply Last reply
              0
              • JonBJ JonB

                @VRonin
                I have made the change (in my own way!) so that the widgets I use have an event filter on dynamic property changes to cause required polishing. I examine QDynamicPropertyChangeEvent::propertyName() and do so only if it's one of mine (like class). There are other cases too (e.g. I make setting/clearing read-only affect line edit's background color).

                How expensive do you think polish/unpolish() (or for that matter re-assigning setStyleSheet() if I chose to do it that way) are?

                The approach we have chosen re-polishes every time I set some "property". However, somewhere in the docs it states we only need to do this when we change a property on something like an already-displayed widget.

                Thus, if I set properties immediately after widget construction --- as I may well do --- I will do re-polishes for each one, even though none of them are necessary. OTOH, if I want to change the properties at a later date after widget has been shown, I would indeed need the re-polishing, but only then.

                I haven't found all the circumstances, but I'm wondering whether my event filter could test something like QWidget::isVisible() before doing the re-polish, so that it does not do it when unnecessarily early in the widget's life-cycle. Any opinion/comment?

                VRoninV Offline
                VRoninV Offline
                VRonin
                wrote on last edited by
                #13

                @JonB said in QObject::setProperty() signalling solution?:

                could test something like QWidget::isVisible() before doing the re-polish

                You certainly could

                "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                ~Napoleon Bonaparte

                On a crusade to banish setIndexWidget() from the holy land of Qt

                JonBJ 1 Reply Last reply
                0
                • VRoninV VRonin

                  @JonB said in QObject::setProperty() signalling solution?:

                  could test something like QWidget::isVisible() before doing the re-polish

                  You certainly could

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

                  @VRonin
                  Do you happen to know the "cost" of unpolish/polish? If it is "cheap", or perhaps "does nothing" on an unshown widget anyway, I won't worry my little head....

                  J.HilkJ 1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #15

                    It is style dependant so there's no unique answer. On windows it looks to be relatively expensive if your widget is not visible

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    2
                    • JonBJ JonB

                      @VRonin
                      Do you happen to know the "cost" of unpolish/polish? If it is "cheap", or perhaps "does nothing" on an unshown widget anyway, I won't worry my little head....

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

                      @JonB it should be at least less expensive than setStyleSheet


                      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
                      1

                      • Login

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