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. problems with signal/slot
Forum Updated to NodeBB v4.3 + New Features

problems with signal/slot

Scheduled Pinned Locked Moved Unsolved General and Desktop
13 Posts 3 Posters 496 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.
  • D Offline
    D Offline
    django.Reinhard
    wrote on last edited by
    #1

    Hi,

    I'm working on conditional constructs, that update the result based on valueChanged signals.

    I have an abstract base class, which registers itself for valueChanged events. In response to that event the class calls a virtual abstract memberfunction and if the result differs from previous evaluation it vomits a signal.

    In my testcase only EqualCondition works as expected. Trying Smaller- or GreaterCondition fails before the evaluation is performed.

    Actually I don't understand the behaviour and for that, I don't know what to change or where to search for alternatives. I tried to debug testcases, but that does not work.
    (I use qtcreator and qt5.15 on linux debian 11)

    So I hope, someone can shine me a light ...

    The abstract declaration:

    
    class AbstractCondition : public QObject
    {
      Q_OBJECT
    public:
      explicit AbstractCondition(ValueModel* model, const QVariant& value, QObject *parent = nullptr);
    
      bool result() { return met; }
    
    public slots:
      virtual bool eval() = 0;
      virtual void update();
    
    signals:
      void conditionChanged(bool result);
    
    protected:
      ValueModel* model() { return m; }
      QVariant    value() { return v; }
    
    private:
      ValueModel* m;
      QVariant    v;
      bool        met;
      };
    
    

    the corresponding implementation:

    
    AbstractCondition::AbstractCondition(ValueModel* model, const QVariant& value, QObject *parent)
     : QObject(parent)
     , m(model)
     , v(value) {
      connect(m, &ValueModel::valueChanged, this, &AbstractCondition::update);
      }
    
    
    void AbstractCondition::update() {
      qDebug() << "AbstractCondition::update() ...";
      bool rv = eval();
    
      qDebug() << "\teval returned: " << (rv ? "true" : "false");
      if (rv != met) {
         met = rv;
         qDebug() << "\tgonna fire condition changed event ...";
         emit  conditionChanged(met);
         }
      }
    

    The working EqualCondition:

    
    EqualCondition::EqualCondition(ValueModel* model, const QVariant& value, QObject *parent)
     : AbstractCondition(model, value, parent) {
      }
    
    
    bool EqualCondition::eval() {
      qDebug() << "EqualCondition::eval() ...";
      if (model()->getValue().type() == value().type())
         return model()->getValue() == value();
      else return false;
      }
    

    the working Testcase:

    class TestEngine : public QObject
    {
      Q_OBJECT
    
    public slots:
      void updateCondition(bool result) { this->result = result; };
    
    private slots:
      void testEqualCondition();
      void testSmallerCondition();
      void testGreaterCondition();
    
    private:
      volatile bool result;
      };
    
    void TestEngine::testEqualCondition() {
      ValueModel vm("equal", 3);
      EqualCondition c(&vm, 7);
    
      connect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
    
      QCOMPARE(result, false);
    
      vm.setValue(7);
    
      QCOMPARE(result, true);
      this->disconnect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
      }
    

    ValueModel is a wrapper around a QVariant which emits valueChanged events when the value changes.

    The failing testcase for SmallerCondition:

    
    void TestEngine::testSmallerCondition() {
      ValueModel v1("small", 3.14);
      SmallerCondition cS(&v1, 2.0);
    
      connect(&cS, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
    
      QCOMPARE(result, false);
    
      v1.setValue(3.15);
    
      QCOMPARE(result, true);
      this->disconnect(&cS, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
      }
    

    and finally the smaller condition implementation:

    
    SmallerCondition::SmallerCondition(ValueModel* model, const QVariant& value, QObject *parent)
     : AbstractCondition(model, value, parent) {
      }
    
    
    bool SmallerCondition::eval() {
      qDebug() << "SmallerCondition::eval() ...";
      switch (model()->getValue().type()) {
        case QMetaType::Char:
        case QMetaType::Short:
        case QMetaType::Int:
        case QMetaType::Long:
        case QMetaType::LongLong:
             qDebug() << "compare signed integers (<): " << model()->getValue().toLongLong()
                      << "\tvalue: " << value().toLongLong();
             return model()->getValue().toLongLong() < value().toLongLong();
        case QMetaType::UChar:
        case QMetaType::UShort:
        case QMetaType::UInt:
        case QMetaType::ULong:
        case QMetaType::ULongLong:
             qDebug() << "compare unsigned integers (<): " << model()->getValue().toLongLong()
                      << "\tvalue: " << value().toLongLong();
             return model()->getValue().toULongLong() < value().toULongLong();
        case QMetaType::Double:
             qDebug() << "compare decimals (<): " << model()->getValue().toDouble()
                      << "\tvalue: " << value().toDouble();
             return model()->getValue().toDouble() < value().toDouble();
        }
      return false;
      }
    
    

    Following the debug output the smallercondition does not receive a valueChanged event and for so evaluation is not performed.

    What am I missing/doing wrong?

    Christian EhrlicherC 1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      What's your implementation of ValueModel? Where do you emit the valueChanged signal?
      And please provide a minimal example, not your whole code so it gets easier to debug your problem.

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

      1 Reply Last reply
      0
      • D Offline
        D Offline
        django.Reinhard
        wrote on last edited by
        #3

        ValueModel

        ValueModel::ValueModel(const QString& name, const QVariant& value)
         : QObject(nullptr)
         , v(value)
         , n(name) {
          }
        
        
        void ValueModel::setValue(const QVariant& value) {
          if (v != value) {
             v = value;
             emit valueChanged(v);
             }
          }
        

        @Christian-Ehrlicher said in problems with signal/slot:

        And please provide a minimal example, not your whole code so it gets easier to debug your problem.

        Less than the posted code?
        That's not possible!

        Christian EhrlicherC 1 Reply Last reply
        0
        • D Offline
          D Offline
          django.Reinhard
          wrote on last edited by
          #4

          I recently was able to debug the testcase and it looks like AbstractCondition::update runs into the part to emit conditionChanged - but that event is not fired.

          Although I connected the signal with the updateCondition method.

          There was no error message at console about failed connect, so I expect that it should work.

          1 Reply Last reply
          0
          • D django.Reinhard

            ValueModel

            ValueModel::ValueModel(const QString& name, const QVariant& value)
             : QObject(nullptr)
             , v(value)
             , n(name) {
              }
            
            
            void ValueModel::setValue(const QVariant& value) {
              if (v != value) {
                 v = value;
                 emit valueChanged(v);
                 }
              }
            

            @Christian-Ehrlicher said in problems with signal/slot:

            And please provide a minimal example, not your whole code so it gets easier to debug your problem.

            Less than the posted code?
            That's not possible!

            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @django-Reinhard said in problems with signal/slot:

            That's not possible!

            It is.... But it's up to you. I won't debug your code above.

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

            1 Reply Last reply
            1
            • D django.Reinhard

              Hi,

              I'm working on conditional constructs, that update the result based on valueChanged signals.

              I have an abstract base class, which registers itself for valueChanged events. In response to that event the class calls a virtual abstract memberfunction and if the result differs from previous evaluation it vomits a signal.

              In my testcase only EqualCondition works as expected. Trying Smaller- or GreaterCondition fails before the evaluation is performed.

              Actually I don't understand the behaviour and for that, I don't know what to change or where to search for alternatives. I tried to debug testcases, but that does not work.
              (I use qtcreator and qt5.15 on linux debian 11)

              So I hope, someone can shine me a light ...

              The abstract declaration:

              
              class AbstractCondition : public QObject
              {
                Q_OBJECT
              public:
                explicit AbstractCondition(ValueModel* model, const QVariant& value, QObject *parent = nullptr);
              
                bool result() { return met; }
              
              public slots:
                virtual bool eval() = 0;
                virtual void update();
              
              signals:
                void conditionChanged(bool result);
              
              protected:
                ValueModel* model() { return m; }
                QVariant    value() { return v; }
              
              private:
                ValueModel* m;
                QVariant    v;
                bool        met;
                };
              
              

              the corresponding implementation:

              
              AbstractCondition::AbstractCondition(ValueModel* model, const QVariant& value, QObject *parent)
               : QObject(parent)
               , m(model)
               , v(value) {
                connect(m, &ValueModel::valueChanged, this, &AbstractCondition::update);
                }
              
              
              void AbstractCondition::update() {
                qDebug() << "AbstractCondition::update() ...";
                bool rv = eval();
              
                qDebug() << "\teval returned: " << (rv ? "true" : "false");
                if (rv != met) {
                   met = rv;
                   qDebug() << "\tgonna fire condition changed event ...";
                   emit  conditionChanged(met);
                   }
                }
              

              The working EqualCondition:

              
              EqualCondition::EqualCondition(ValueModel* model, const QVariant& value, QObject *parent)
               : AbstractCondition(model, value, parent) {
                }
              
              
              bool EqualCondition::eval() {
                qDebug() << "EqualCondition::eval() ...";
                if (model()->getValue().type() == value().type())
                   return model()->getValue() == value();
                else return false;
                }
              

              the working Testcase:

              class TestEngine : public QObject
              {
                Q_OBJECT
              
              public slots:
                void updateCondition(bool result) { this->result = result; };
              
              private slots:
                void testEqualCondition();
                void testSmallerCondition();
                void testGreaterCondition();
              
              private:
                volatile bool result;
                };
              
              void TestEngine::testEqualCondition() {
                ValueModel vm("equal", 3);
                EqualCondition c(&vm, 7);
              
                connect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
              
                QCOMPARE(result, false);
              
                vm.setValue(7);
              
                QCOMPARE(result, true);
                this->disconnect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                }
              

              ValueModel is a wrapper around a QVariant which emits valueChanged events when the value changes.

              The failing testcase for SmallerCondition:

              
              void TestEngine::testSmallerCondition() {
                ValueModel v1("small", 3.14);
                SmallerCondition cS(&v1, 2.0);
              
                connect(&cS, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
              
                QCOMPARE(result, false);
              
                v1.setValue(3.15);
              
                QCOMPARE(result, true);
                this->disconnect(&cS, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                }
              

              and finally the smaller condition implementation:

              
              SmallerCondition::SmallerCondition(ValueModel* model, const QVariant& value, QObject *parent)
               : AbstractCondition(model, value, parent) {
                }
              
              
              bool SmallerCondition::eval() {
                qDebug() << "SmallerCondition::eval() ...";
                switch (model()->getValue().type()) {
                  case QMetaType::Char:
                  case QMetaType::Short:
                  case QMetaType::Int:
                  case QMetaType::Long:
                  case QMetaType::LongLong:
                       qDebug() << "compare signed integers (<): " << model()->getValue().toLongLong()
                                << "\tvalue: " << value().toLongLong();
                       return model()->getValue().toLongLong() < value().toLongLong();
                  case QMetaType::UChar:
                  case QMetaType::UShort:
                  case QMetaType::UInt:
                  case QMetaType::ULong:
                  case QMetaType::ULongLong:
                       qDebug() << "compare unsigned integers (<): " << model()->getValue().toLongLong()
                                << "\tvalue: " << value().toLongLong();
                       return model()->getValue().toULongLong() < value().toULongLong();
                  case QMetaType::Double:
                       qDebug() << "compare decimals (<): " << model()->getValue().toDouble()
                                << "\tvalue: " << value().toDouble();
                       return model()->getValue().toDouble() < value().toDouble();
                  }
                return false;
                }
              
              

              Following the debug output the smallercondition does not receive a valueChanged event and for so evaluation is not performed.

              What am I missing/doing wrong?

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @django-Reinhard said in problems with signal/slot:

              bool met;

              btw: This value is uninitialized.

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

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

                Hi,

                You're checking for almost all numerical types except float.

                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
                • D Offline
                  D Offline
                  django.Reinhard
                  wrote on last edited by
                  #8

                  @Christian-Ehrlicher said in problems with signal/slot:

                  btw: This value is uninitialized.

                  @SGaist said in problems with signal/slot:

                  You're checking for almost all numerical types except float.

                  Both issues are fixed.
                  I uploaded a stripped testproject

                  Console output with debug messages enabled:

                  QDEBUG : TestEngine::testEqualCondition() AbstractCondition::update() ...
                  QDEBUG : TestEngine::testEqualCondition() EqualCondition::eval() ...
                  QDEBUG : TestEngine::testEqualCondition() 	eval returned:  false
                  QDEBUG : TestEngine::testEqualCondition() 	gonna fire condition changed event ...
                  QDEBUG : TestEngine::testEqualCondition() AbstractCondition::update() ...
                  QDEBUG : TestEngine::testEqualCondition() EqualCondition::eval() ...
                  QDEBUG : TestEngine::testEqualCondition() 	eval returned:  true
                  QDEBUG : TestEngine::testEqualCondition() 	gonna fire condition changed event ...
                  PASS   : TestEngine::testEqualCondition()
                  QDEBUG : TestEngine::testSmallerCondition() AbstractCondition::update() ...
                  QDEBUG : TestEngine::testSmallerCondition() SmallerCondition::eval() ...
                  QDEBUG : TestEngine::testSmallerCondition() compare decimals (<):  3.14 	value:  2
                  QDEBUG : TestEngine::testSmallerCondition() 	eval returned:  false
                  QDEBUG : TestEngine::testSmallerCondition() 	gonna fire condition changed event ...
                  FAIL!  : TestEngine::testSmallerCondition() Compared values are not the same
                     Loc: [../Scratch/src/test/testengine.cpp(50)]
                  QDEBUG : TestEngine::testGreaterCondition() AbstractCondition::update() ...
                  QDEBUG : TestEngine::testGreaterCondition() GreaterCondition::eval() ...
                  QDEBUG : TestEngine::testGreaterCondition() compare signed integers (>):  97 	value:  114
                  QDEBUG : TestEngine::testGreaterCondition() 	eval returned:  false
                  QDEBUG : TestEngine::testGreaterCondition() 	gonna fire condition changed event ...
                  FAIL!  : TestEngine::testGreaterCondition() Compared values are not the same
                     Loc: [../Scratch/src/test/testengine.cpp(65)]
                  

                  which shows, that EqualCondition emits the signal, whereas SmallerCondition and GreaterCondition don't emit the signal.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Offline
                    Christian EhrlicherC Offline
                    Christian Ehrlicher
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    volatile bool result;

                    still an uninitialized variable and what should volatile do here? You should al

                    And wrt your problem. Your conditionChanged event is only fired when the condition changes which is not the case for testSmallerCondition(). Also you can't catch the first conditionChanged event in each of your functions because it's fired in the ctor when you not yet connect the signal.

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

                    1 Reply Last reply
                    1
                    • D Offline
                      D Offline
                      django.Reinhard
                      wrote on last edited by
                      #10

                      @Christian-Ehrlicher said in problems with signal/slot:

                      still an uninitialized variable

                      That may be true, but I don't use the variable before it is set.

                      @Christian-Ehrlicher said in problems with signal/slot:

                      what should volatile do here?
                      It was a try to disable possible compiler optimizations ...

                      @Christian-Ehrlicher said in problems with signal/slot:

                      Also you can't catch the first conditionChanged event in each of your functions because it's fired in the ctor when you not yet connect the signal.

                      If that would be true, then please explain, why does it work for EqualCondition? It does not accidently pass the test.
                      Since the beginning this test always has been passed.

                      Christian EhrlicherC 1 Reply Last reply
                      0
                      • D django.Reinhard

                        @Christian-Ehrlicher said in problems with signal/slot:

                        still an uninitialized variable

                        That may be true, but I don't use the variable before it is set.

                        @Christian-Ehrlicher said in problems with signal/slot:

                        what should volatile do here?
                        It was a try to disable possible compiler optimizations ...

                        @Christian-Ehrlicher said in problems with signal/slot:

                        Also you can't catch the first conditionChanged event in each of your functions because it's fired in the ctor when you not yet connect the signal.

                        If that would be true, then please explain, why does it work for EqualCondition? It does not accidently pass the test.
                        Since the beginning this test always has been passed.

                        Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by Christian Ehrlicher
                        #11

                        @django-Reinhard said in problems with signal/slot:

                        It does not accidently pass the test.

                        It does because your setup is different there. Your second call to setValue() actually changes the condition whereas it does not for testSmallerCondition()

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

                        1 Reply Last reply
                        3
                        • D Offline
                          D Offline
                          django.Reinhard
                          wrote on last edited by
                          #12

                          You where right indeed!

                          I changed the testcase like this:

                            ValueModel v("small", 3.14);
                            SmallerCondition c(&v, 2.0);
                          
                            connect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                          
                            QCOMPARE(result = c.result(), false);
                          
                            v.setValue(1.15);
                          
                            QCOMPARE(result, true);
                            this->disconnect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                          
                          

                          and now it works.
                          So the call from constructor can't change testresult - but with Equalcondition it did it nevertheless ...

                          Anyway - I understand the source of evil and with the changed code it works reliably.

                          Thank you!

                          Christian EhrlicherC 1 Reply Last reply
                          0
                          • D django.Reinhard

                            You where right indeed!

                            I changed the testcase like this:

                              ValueModel v("small", 3.14);
                              SmallerCondition c(&v, 2.0);
                            
                              connect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                            
                              QCOMPARE(result = c.result(), false);
                            
                              v.setValue(1.15);
                            
                              QCOMPARE(result, true);
                              this->disconnect(&c, &AbstractCondition::conditionChanged, this, &TestEngine::updateCondition);
                            
                            

                            and now it works.
                            So the call from constructor can't change testresult - but with Equalcondition it did it nevertheless ...

                            Anyway - I understand the source of evil and with the changed code it works reliably.

                            Thank you!

                            Christian EhrlicherC Offline
                            Christian EhrlicherC Offline
                            Christian Ehrlicher
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            @django-Reinhard said in problems with signal/slot:

                            but with Equalcondition it did it nevertheless ...

                            No it does not.

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

                            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