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. Can someone explain how the new qt5 signals and slots work
Forum Updated to NodeBB v4.3 + New Features

Can someone explain how the new qt5 signals and slots work

Scheduled Pinned Locked Moved Solved General and Desktop
20 Posts 6 Posters 6.5k Views 4 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.
  • AsimovA Offline
    AsimovA Offline
    Asimov
    wrote on last edited by Asimov
    #1

    I was wondering if someone could explain how the new qt5 signals and slots work I am new to the old ones, let alone the new ones. I know you have to have a signal and a slot, but they have even removed the keywords in the new version, and it doesn't seem so easy to read. I have read the documentation, but reading and understanding are two different things.

    For instance I have this

    QObject::connect(modelBox, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(updateBoxList(const QModelIndex & , const QModelIndex &)));
    

    And the new format is this.

    QObject::connect(modelBox, &QSlider::valueChanged,this, &QProgressBar::setValue);
    

    What I don't understand is where is the signal, and where is the slot.
    Why has QSlider replaced the Signal keyword, and there is no SLOT keyword. It is hard for me to grasp the concept of this new design.

    I know what a QSlider, and I know what QProgressBar does, but I don't know how to add my dataChanged part and then call my function.

    Don't get me wrong my code is working, but I am trying to get my head around the new syntax.

    Any help would be appreciated. I have only been using QT for just over a week, so I am very new.

    A jsulmJ E 3 Replies Last reply
    0
    • AsimovA Asimov

      I was wondering if someone could explain how the new qt5 signals and slots work I am new to the old ones, let alone the new ones. I know you have to have a signal and a slot, but they have even removed the keywords in the new version, and it doesn't seem so easy to read. I have read the documentation, but reading and understanding are two different things.

      For instance I have this

      QObject::connect(modelBox, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(updateBoxList(const QModelIndex & , const QModelIndex &)));
      

      And the new format is this.

      QObject::connect(modelBox, &QSlider::valueChanged,this, &QProgressBar::setValue);
      

      What I don't understand is where is the signal, and where is the slot.
      Why has QSlider replaced the Signal keyword, and there is no SLOT keyword. It is hard for me to grasp the concept of this new design.

      I know what a QSlider, and I know what QProgressBar does, but I don't know how to add my dataChanged part and then call my function.

      Don't get me wrong my code is working, but I am trying to get my head around the new syntax.

      Any help would be appreciated. I have only been using QT for just over a week, so I am very new.

      A Offline
      A Offline
      ambershark
      wrote on last edited by
      #2

      @Asimov Well first off you don't have to use the new format. In many cases I still use SIGNAL() and SLOT() format.

      The new format has it's pros and cons. One of the very big pros is the ability to use a lambda for the slot. So you can do something like:

      connect(obj, &MyObject:mySignal, [=]() { doSomethingHere(); });

      That eliminates the need for defining slots when doing something quick, like say printing a message, updating a label, changing a counter, etc. It can all be done inline with a lambda.

      Here is an article on the differences between old and new method https://wiki.qt.io/New_Signal_Slot_Syntax.

      That should explain it all to you. :)

      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

      J.HilkJ 1 Reply Last reply
      2
      • AsimovA Asimov

        I was wondering if someone could explain how the new qt5 signals and slots work I am new to the old ones, let alone the new ones. I know you have to have a signal and a slot, but they have even removed the keywords in the new version, and it doesn't seem so easy to read. I have read the documentation, but reading and understanding are two different things.

        For instance I have this

        QObject::connect(modelBox, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(updateBoxList(const QModelIndex & , const QModelIndex &)));
        

        And the new format is this.

        QObject::connect(modelBox, &QSlider::valueChanged,this, &QProgressBar::setValue);
        

        What I don't understand is where is the signal, and where is the slot.
        Why has QSlider replaced the Signal keyword, and there is no SLOT keyword. It is hard for me to grasp the concept of this new design.

        I know what a QSlider, and I know what QProgressBar does, but I don't know how to add my dataChanged part and then call my function.

        Don't get me wrong my code is working, but I am trying to get my head around the new syntax.

        Any help would be appreciated. I have only been using QT for just over a week, so I am very new.

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @Asimov said in Can someone explain how the new qt5 signals and slots work:

        QObject::connect(modelBox, &QSlider::valueChanged,this, &QProgressBar::setValue);

        In your example &QSlider::valueChanged is the pointer to the signal and &QProgressBar::setValue is the pointer to the slot, so the order is the same as in the old connect.
        See here for more information: https://wiki.qt.io/New_Signal_Slot_Syntax

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • A ambershark

          @Asimov Well first off you don't have to use the new format. In many cases I still use SIGNAL() and SLOT() format.

          The new format has it's pros and cons. One of the very big pros is the ability to use a lambda for the slot. So you can do something like:

          connect(obj, &MyObject:mySignal, [=]() { doSomethingHere(); });

          That eliminates the need for defining slots when doing something quick, like say printing a message, updating a label, changing a counter, etc. It can all be done inline with a lambda.

          Here is an article on the differences between old and new method https://wiki.qt.io/New_Signal_Slot_Syntax.

          That should explain it all to you. :)

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

          @ambershark @Asimov

          an additional note to lambdas.

          You could potentially do something like this:

          QLabel *lbl_1 = new QLabel();
          lbl_1->setText("I'm a Label");
          connect(sender, &Sender::updateLabels, [=](const QString &newValue) {
            lbl_1->setText(newValue);
          });
          

          and it works!

          But,if you write it like this and your lbl_1 is for whatever reason deleted, your app will crash the next time updateLabels is called.
          However, since 5.2 there is an overload which adds a "context object". When that object is destroyed, the connection is broken.
          I haven't seen this documented well enough yet, maybe someone can point me in the right direction.

          You can simply change the connect statement to this:

          connect(sender, &Sender::updateLabels, lbl_1,[=](const QString &newValue) {
            lbl_1->setText(newValue);
          });
          

          and the connection will be removed, whenn lbl_1 ceases to exist.


          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.

          A 1 Reply Last reply
          0
          • J.HilkJ J.Hilk

            @ambershark @Asimov

            an additional note to lambdas.

            You could potentially do something like this:

            QLabel *lbl_1 = new QLabel();
            lbl_1->setText("I'm a Label");
            connect(sender, &Sender::updateLabels, [=](const QString &newValue) {
              lbl_1->setText(newValue);
            });
            

            and it works!

            But,if you write it like this and your lbl_1 is for whatever reason deleted, your app will crash the next time updateLabels is called.
            However, since 5.2 there is an overload which adds a "context object". When that object is destroyed, the connection is broken.
            I haven't seen this documented well enough yet, maybe someone can point me in the right direction.

            You can simply change the connect statement to this:

            connect(sender, &Sender::updateLabels, lbl_1,[=](const QString &newValue) {
              lbl_1->setText(newValue);
            });
            

            and the connection will be removed, whenn lbl_1 ceases to exist.

            A Offline
            A Offline
            ambershark
            wrote on last edited by
            #5

            @J.Hilk Could you not just add a check in your lambda, something like if (lbl_1) lbl_1->setText(newValue); and when you clean up lbl_1 set it to nullptr.

            I honestly haven't played with the new style signals and slots much. Out of many years of habit I tend to use the SIGNAL() and SLOT() macros unless I specifically need a lambda. So I haven't run into these crash scenarios yet.

            My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

            J.HilkJ 1 Reply Last reply
            0
            • A ambershark

              @J.Hilk Could you not just add a check in your lambda, something like if (lbl_1) lbl_1->setText(newValue); and when you clean up lbl_1 set it to nullptr.

              I honestly haven't played with the new style signals and slots much. Out of many years of habit I tend to use the SIGNAL() and SLOT() macros unless I specifically need a lambda. So I haven't run into these crash scenarios yet.

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

              @ambershark
              yes of course you can do it that way, In fact before I found the overload context object that is how I handled this kind of situations.

              But the problem is, the connection still existes and takes up a cycle of the cpu. Doesn't seem like much, but if one is not careful, it can explode pretty quickly.

              There's also the possibility of a manuel disconnect:

              QMetaObject::Connection m_connection;
              //…
              m_connection = QObject::connect(…);
              //…
              QObject::disconnect(m_connection);
              

              But that can mean lots of new member variables or at least many more lines of code.

              The best solution, is in deed - in my opinion - to pass the refered context object to the QObject::Connect:

              connect(sender, &Sender::updateLabels, lbl_1,[=](const QString &newValue) {
              lbl_1->setText(newValue);
              });

              and let Qt handle the potential disconnect internally.


              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.

              A 1 Reply Last reply
              1
              • J.HilkJ J.Hilk

                @ambershark
                yes of course you can do it that way, In fact before I found the overload context object that is how I handled this kind of situations.

                But the problem is, the connection still existes and takes up a cycle of the cpu. Doesn't seem like much, but if one is not careful, it can explode pretty quickly.

                There's also the possibility of a manuel disconnect:

                QMetaObject::Connection m_connection;
                //…
                m_connection = QObject::connect(…);
                //…
                QObject::disconnect(m_connection);
                

                But that can mean lots of new member variables or at least many more lines of code.

                The best solution, is in deed - in my opinion - to pass the refered context object to the QObject::Connect:

                connect(sender, &Sender::updateLabels, lbl_1,[=](const QString &newValue) {
                lbl_1->setText(newValue);
                });

                and let Qt handle the potential disconnect internally.

                A Offline
                A Offline
                ambershark
                wrote on last edited by ambershark
                #7

                @J.Hilk Yea that sounds like the preferred way for me too. I would much rather have Qt handle it. I don't want to save connection variables and deal with disconnecting them later.

                And I definitely don't want to have all my signals build up and need to be checked even after they are no longer relevant. That is definitely a waste of CPU cycles and it all adds up. It will never be as slow as Java though. ;P

                My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                1 Reply Last reply
                1
                • AsimovA Asimov

                  I was wondering if someone could explain how the new qt5 signals and slots work I am new to the old ones, let alone the new ones. I know you have to have a signal and a slot, but they have even removed the keywords in the new version, and it doesn't seem so easy to read. I have read the documentation, but reading and understanding are two different things.

                  For instance I have this

                  QObject::connect(modelBox, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),this,SLOT(updateBoxList(const QModelIndex & , const QModelIndex &)));
                  

                  And the new format is this.

                  QObject::connect(modelBox, &QSlider::valueChanged,this, &QProgressBar::setValue);
                  

                  What I don't understand is where is the signal, and where is the slot.
                  Why has QSlider replaced the Signal keyword, and there is no SLOT keyword. It is hard for me to grasp the concept of this new design.

                  I know what a QSlider, and I know what QProgressBar does, but I don't know how to add my dataChanged part and then call my function.

                  Don't get me wrong my code is working, but I am trying to get my head around the new syntax.

                  Any help would be appreciated. I have only been using QT for just over a week, so I am very new.

                  E Offline
                  E Offline
                  Eeli K
                  wrote on last edited by
                  #8

                  @Asimov You seem to have too different connections - different signals and slots - in your example. The structure of both is

                  sender_object, signal, receiver_object, slot

                  In the old syntax you need to mark the signal and slot with macro markers. With the new one they are not needed, but you have to give the signal and slot in form of

                  the_address_of_the_member_function

                  which is

                  a_pointer_to_the_member_function

                  which is expressed as

                  &class_name::function_name

                  I don't know how much you know low-level C/C++ stuff. If you know how pointers to functions work you understand this. The member functions of a class reside somewhere in the memory. Each function is common to all objects of that class, as is all static data. Only the normal data members are per-object. So basically what you need to call a member function of an object is the object and the pointer to the member function. And you can get the pointer through the class. Therefore you use both the object name and the class name in the new syntax.

                  On important aspect of the new syntax is that it checks compile time that the signal and slot are compatible. I sometimes have run in a situation where in the old syntax I got the arguments wrong and the connection didn't work but it doesn't give any error. In the case where there are no overloads I find the new syntax short and clear and easy to type after you have been accustomed to the syntax.

                  In some cases you may run into problems if you don't know all the details. See for example QAbstractSocket::error.

                  Note: Signal error is overloaded in this class. To connect to this one using the function pointer syntax, you must specify the signal type in a static cast, as shown in this example:
                  
                  connect(abstractSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                      [=](QAbstractSocket::SocketError socketError){ /* ... */ });
                  

                  Unfortunately it wasn't documented in a place where I tried to look at (the signal/slot documentation) but the compiler gave errors which I didn't understand. The old syntax worked. No need to say how ugly and difficult this new syntax with static_cast is...

                  J.HilkJ AsimovA 2 Replies Last reply
                  3
                  • E Eeli K

                    @Asimov You seem to have too different connections - different signals and slots - in your example. The structure of both is

                    sender_object, signal, receiver_object, slot

                    In the old syntax you need to mark the signal and slot with macro markers. With the new one they are not needed, but you have to give the signal and slot in form of

                    the_address_of_the_member_function

                    which is

                    a_pointer_to_the_member_function

                    which is expressed as

                    &class_name::function_name

                    I don't know how much you know low-level C/C++ stuff. If you know how pointers to functions work you understand this. The member functions of a class reside somewhere in the memory. Each function is common to all objects of that class, as is all static data. Only the normal data members are per-object. So basically what you need to call a member function of an object is the object and the pointer to the member function. And you can get the pointer through the class. Therefore you use both the object name and the class name in the new syntax.

                    On important aspect of the new syntax is that it checks compile time that the signal and slot are compatible. I sometimes have run in a situation where in the old syntax I got the arguments wrong and the connection didn't work but it doesn't give any error. In the case where there are no overloads I find the new syntax short and clear and easy to type after you have been accustomed to the syntax.

                    In some cases you may run into problems if you don't know all the details. See for example QAbstractSocket::error.

                    Note: Signal error is overloaded in this class. To connect to this one using the function pointer syntax, you must specify the signal type in a static cast, as shown in this example:
                    
                    connect(abstractSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                        [=](QAbstractSocket::SocketError socketError){ /* ... */ });
                    

                    Unfortunately it wasn't documented in a place where I tried to look at (the signal/slot documentation) but the compiler gave errors which I didn't understand. The old syntax worked. No need to say how ugly and difficult this new syntax with static_cast is...

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

                    @Eeli-K
                    a quick addition to that with qt5.7 we canshorten overload /static_cast drastically:

                    //static_cast of overloaded functions:
                    QObject::connect(
                            a,
                            static_cast<void(MyObject::*)(int)>(&MyObject::signal),
                            b,
                            static_cast<void(MyObject::*)(int)>(&MyObject::slot));
                    
                    // Qt 5.7 + allows qOverload, but it requires C++14 to be enabled:
                        QObject::connect(
                            a,
                            qOverload<int>(&MyObject::signal),
                            b,
                            qOverload<int>(&MyObject::slot));
                    
                    // slightly longer, but works in C++11:
                        QObject::connect(
                            a,
                            QOverload<int>::of(&MyObject::signal),
                            b,
                            QOverload<int>::of(&MyObject::slot));
                    

                    Example taken from here:


                    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
                    4
                    • E Eeli K

                      @Asimov You seem to have too different connections - different signals and slots - in your example. The structure of both is

                      sender_object, signal, receiver_object, slot

                      In the old syntax you need to mark the signal and slot with macro markers. With the new one they are not needed, but you have to give the signal and slot in form of

                      the_address_of_the_member_function

                      which is

                      a_pointer_to_the_member_function

                      which is expressed as

                      &class_name::function_name

                      I don't know how much you know low-level C/C++ stuff. If you know how pointers to functions work you understand this. The member functions of a class reside somewhere in the memory. Each function is common to all objects of that class, as is all static data. Only the normal data members are per-object. So basically what you need to call a member function of an object is the object and the pointer to the member function. And you can get the pointer through the class. Therefore you use both the object name and the class name in the new syntax.

                      On important aspect of the new syntax is that it checks compile time that the signal and slot are compatible. I sometimes have run in a situation where in the old syntax I got the arguments wrong and the connection didn't work but it doesn't give any error. In the case where there are no overloads I find the new syntax short and clear and easy to type after you have been accustomed to the syntax.

                      In some cases you may run into problems if you don't know all the details. See for example QAbstractSocket::error.

                      Note: Signal error is overloaded in this class. To connect to this one using the function pointer syntax, you must specify the signal type in a static cast, as shown in this example:
                      
                      connect(abstractSocket, static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                          [=](QAbstractSocket::SocketError socketError){ /* ... */ });
                      

                      Unfortunately it wasn't documented in a place where I tried to look at (the signal/slot documentation) but the compiler gave errors which I didn't understand. The old syntax worked. No need to say how ugly and difficult this new syntax with static_cast is...

                      AsimovA Offline
                      AsimovA Offline
                      Asimov
                      wrote on last edited by Asimov
                      #10

                      @Eeli-K
                      I know a little bit about pointers a * denotes a pointer to a variable, and an & is the address of the variable at it's simplest term.

                      The reason I want to learn the new format is that I am worried they will get rid of the old format which I have only just learnt.

                      @Everyone
                      If a signal is not marked with a Macro how do I do the datachanged. It is for a QTableView so would I do something like &QTableView::dataChanged or something?

                      I haven't read all these posts properly yet, but going to have a good read now.

                      Thanks for all the replies. I am not new to C++ but I have got a little rusty because I haven't done much for a few years, while 3D Modelling.
                      I am however new to QT.

                      PS. I just tried QTableView::dataChanged and it doesn't work LOL.
                      PPS. I don't know what Lambda means.

                      A E 2 Replies Last reply
                      0
                      • AsimovA Asimov

                        @Eeli-K
                        I know a little bit about pointers a * denotes a pointer to a variable, and an & is the address of the variable at it's simplest term.

                        The reason I want to learn the new format is that I am worried they will get rid of the old format which I have only just learnt.

                        @Everyone
                        If a signal is not marked with a Macro how do I do the datachanged. It is for a QTableView so would I do something like &QTableView::dataChanged or something?

                        I haven't read all these posts properly yet, but going to have a good read now.

                        Thanks for all the replies. I am not new to C++ but I have got a little rusty because I haven't done much for a few years, while 3D Modelling.
                        I am however new to QT.

                        PS. I just tried QTableView::dataChanged and it doesn't work LOL.
                        PPS. I don't know what Lambda means.

                        A Offline
                        A Offline
                        ambershark
                        wrote on last edited by
                        #11

                        @Asimov http://en.cppreference.com/w/cpp/language/lambda.

                        Show us how you did the dataChanged signal.

                        My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                        AsimovA 1 Reply Last reply
                        0
                        • AsimovA Asimov

                          @Eeli-K
                          I know a little bit about pointers a * denotes a pointer to a variable, and an & is the address of the variable at it's simplest term.

                          The reason I want to learn the new format is that I am worried they will get rid of the old format which I have only just learnt.

                          @Everyone
                          If a signal is not marked with a Macro how do I do the datachanged. It is for a QTableView so would I do something like &QTableView::dataChanged or something?

                          I haven't read all these posts properly yet, but going to have a good read now.

                          Thanks for all the replies. I am not new to C++ but I have got a little rusty because I haven't done much for a few years, while 3D Modelling.
                          I am however new to QT.

                          PS. I just tried QTableView::dataChanged and it doesn't work LOL.
                          PPS. I don't know what Lambda means.

                          E Offline
                          E Offline
                          Eeli K
                          wrote on last edited by
                          #12

                          @Asimov Yes, & takes the address of a variable. In this case is takes the address of a function. You can store the address to a variable which is a pointer to a function. In C++11, which is required anyways by the new signal/slot syntax, you can do

                          auto sgnl = &QSlider::valueChanged;
                          auto slt = &QProgressBar::setValue;
                          QObject::connect(modelBox, sgnl, this, slt);
                          

                          sgnl and slt are pointers to functions (signals are also functions). I don't even try to find out their types explicitly - that's where the auto keyword is very handy - but you can see some details in http://www.cprogramming.com/tutorial/function-pointers.html. (See also "Related articles" there.)

                          You don't have to be afraid of them getting rid of the old syntax. Maybe after 10 or 15 years, but they don't want to break existing working code and can't (yet) get rid of the MOC (Meta Object Compiler which creates C++ code out of Q_OBJECT, signals:, slots: etc.) even if they wanted to. You can read https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html and https://woboq.com/blog/verdigris-qt-without-moc.html for some in-depth discussion about MOC.

                          1 Reply Last reply
                          0
                          • A ambershark

                            @Asimov http://en.cppreference.com/w/cpp/language/lambda.

                            Show us how you did the dataChanged signal.

                            AsimovA Offline
                            AsimovA Offline
                            Asimov
                            wrote on last edited by Asimov
                            #13

                            @ambershark
                            I didn't have to do this signal, it is part of the QAbstractItemModel, and I am using it on a QStandardItemModel in a QTableView
                            ie
                            http://doc.qt.io/qt-4.8/qabstractitemmodel.html#dataChanged

                            My signal and slot are working fine. I just wanted to know how to do it the qt5 way.
                            PS. I have already read that article, but found it as clear as mud LOL.

                            @Eeli-K
                            It's nice to know they are keeping the old system for a while, but I would like to understand the new system.
                            @jsulm
                            The second was just an example, and I kinda understand how that works, but I don't understand how to use my datachange example in the new format.

                            PS. Just found out that Lambda's are like little functions with no name. Not heard of these before.
                            PPS.
                            Just tried this. I think I am close

                            QObject::connect(modelBox,&QAbstractItemModel::dataChanged(const QModelIndex &),this,&DbManager::updateBoxList(const QModelIndex &));
                            

                            But it is giving me an error at the end. I don't think &DbManager is right. It is the name of my class which updateBoxList is in.

                            E 1 Reply Last reply
                            0
                            • AsimovA Asimov

                              @ambershark
                              I didn't have to do this signal, it is part of the QAbstractItemModel, and I am using it on a QStandardItemModel in a QTableView
                              ie
                              http://doc.qt.io/qt-4.8/qabstractitemmodel.html#dataChanged

                              My signal and slot are working fine. I just wanted to know how to do it the qt5 way.
                              PS. I have already read that article, but found it as clear as mud LOL.

                              @Eeli-K
                              It's nice to know they are keeping the old system for a while, but I would like to understand the new system.
                              @jsulm
                              The second was just an example, and I kinda understand how that works, but I don't understand how to use my datachange example in the new format.

                              PS. Just found out that Lambda's are like little functions with no name. Not heard of these before.
                              PPS.
                              Just tried this. I think I am close

                              QObject::connect(modelBox,&QAbstractItemModel::dataChanged(const QModelIndex &),this,&DbManager::updateBoxList(const QModelIndex &));
                              

                              But it is giving me an error at the end. I don't think &DbManager is right. It is the name of my class which updateBoxList is in.

                              E Offline
                              E Offline
                              Eeli K
                              wrote on last edited by
                              #14

                              @Asimov Well, there is only

                              [signal] void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int> ())
                              

                              in QAbstractItemModel, so &QAbstractItemModel::dataChanged(const QModelIndex &) doesn't work. Don't keep teasing us, give us the error message. Have you tried

                              QObject::connect(modelBox,&QAbstractItemModel::dataChanged,this,&DbManager::updateBoxList);
                              

                              ? The niceness of this is that if neither signal nor slot are overloaded you should be able to leave off the arguments because the function names are unambiguous.

                              If you really want to understand the new system, look at https://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html. But it's quite techical, too.

                              1 Reply Last reply
                              1
                              • AsimovA Offline
                                AsimovA Offline
                                Asimov
                                wrote on last edited by Asimov
                                #15

                                @Eeli-K
                                Hey that worked, it called my function. That wasn't as bad as I thought.
                                I knew I was close, just couldn't get the syntax.

                                I wonder if there is any way to send the table index to my function?

                                But the good news is that my function is being called.

                                PS. I managed to get the index like this

                                void DbManager::updateBoxList(const QModelIndex &index){
                                    qDebug() << "index: " << index.row();
                                }
                                

                                This is must better than the original signal and slots I originally used.

                                A 1 Reply Last reply
                                0
                                • AsimovA Asimov

                                  @Eeli-K
                                  Hey that worked, it called my function. That wasn't as bad as I thought.
                                  I knew I was close, just couldn't get the syntax.

                                  I wonder if there is any way to send the table index to my function?

                                  But the good news is that my function is being called.

                                  PS. I managed to get the index like this

                                  void DbManager::updateBoxList(const QModelIndex &index){
                                      qDebug() << "index: " << index.row();
                                  }
                                  

                                  This is must better than the original signal and slots I originally used.

                                  A Offline
                                  A Offline
                                  ambershark
                                  wrote on last edited by
                                  #16

                                  @Asimov You already get the indexes with that call you are making to connect. Just so you know with that updateBoxList call you are only getting the topLeft index, so if you ever update more than 1 index, you don't handle that case... for that you would need:

                                  void DbManager::updateBoxList(const QModelIndex &topLeft, const QModelIndex &buttomRight)
                                  {
                                  }
                                  

                                  My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                  1 Reply Last reply
                                  0
                                  • AsimovA Offline
                                    AsimovA Offline
                                    Asimov
                                    wrote on last edited by Asimov
                                    #17

                                    Yes ambershark &topleft gives me what my index was giving me. Really I think all I was doing was renaming &topleft to index if you think about it. Thanks. So the new format isn't so bad after all, just takes a bit of getting used to.
                                    Thanks to everyone who answered as well. Been a great help.

                                    BTW I keep looking at your avatar and thinking firefox, and then I look again and it looks like a fish.

                                    A 1 Reply Last reply
                                    0
                                    • AsimovA Asimov

                                      Yes ambershark &topleft gives me what my index was giving me. Really I think all I was doing was renaming &topleft to index if you think about it. Thanks. So the new format isn't so bad after all, just takes a bit of getting used to.
                                      Thanks to everyone who answered as well. Been a great help.

                                      BTW I keep looking at your avatar and thinking firefox, and then I look again and it looks like a fish.

                                      A Offline
                                      A Offline
                                      ambershark
                                      wrote on last edited by
                                      #18

                                      @Asimov Lol yea it's a shark... an amber one. ;) My company logo. I never thought about it but it does kind of share a flow with firefox. The whole circular animal logo thing.

                                      Yea you were just renaming topLeft to index which is fine I was just pointing out that if you don't use topleft and bottomright and have multiple index changes than your "index" will not be what you expect it to be. If you control updates to always be a single index you'll be fine though.

                                      My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                      1 Reply Last reply
                                      0
                                      • AsimovA Offline
                                        AsimovA Offline
                                        Asimov
                                        wrote on last edited by
                                        #19

                                        I know I marked this as solved, but I just wanted you to know I am still learning. I also had another couple of other signals and slots which used the old format, but seeing as they were still working I didn't change it straight away, and now I have managed to change it to the new format without any problems.

                                        Old Format

                                        connect(searchButton, SIGNAL(clicked()),this,SLOT(on_searchButton_clicked()));
                                        connect(lineEdit, SIGNAL(returnPressed()),this,SLOT(on_searchButton_clicked()));
                                        

                                        And re-written in new format

                                        connect(searchButton,&QPushButton::clicked,this,&MainWindow::on_searchButton_clicked);
                                        connect(lineEdit,&QLineEdit::returnPressed,this,&MainWindow::on_searchButton_clicked);
                                        

                                        I probably only scratched the surface with signals and slots, but I am progressing slowly. Thanks all.

                                        kshegunovK 1 Reply Last reply
                                        0
                                        • AsimovA Asimov

                                          I know I marked this as solved, but I just wanted you to know I am still learning. I also had another couple of other signals and slots which used the old format, but seeing as they were still working I didn't change it straight away, and now I have managed to change it to the new format without any problems.

                                          Old Format

                                          connect(searchButton, SIGNAL(clicked()),this,SLOT(on_searchButton_clicked()));
                                          connect(lineEdit, SIGNAL(returnPressed()),this,SLOT(on_searchButton_clicked()));
                                          

                                          And re-written in new format

                                          connect(searchButton,&QPushButton::clicked,this,&MainWindow::on_searchButton_clicked);
                                          connect(lineEdit,&QLineEdit::returnPressed,this,&MainWindow::on_searchButton_clicked);
                                          

                                          I probably only scratched the surface with signals and slots, but I am progressing slowly. Thanks all.

                                          kshegunovK Offline
                                          kshegunovK Offline
                                          kshegunov
                                          Moderators
                                          wrote on last edited by
                                          #20

                                          @Asimov said in Can someone explain how the new qt5 signals and slots work:

                                          I probably only scratched the surface with signals and slots, but I am progressing slowly. Thanks all.

                                          Probably not. If you understand the old syntax and understand how pointer-to-member (and/or function pointers) work then you know it all. The new Qt syntax is nothing else but the old syntax modified to be a handy wrap around the pointer-to-member syntax C++ provides.

                                          For completeness, a pointer to member is a function pointer, and a function pointer is a variable that stores the address of a function. Functions reside in the static part of the program (as Eeli K already noted). So you can get the address of that piece of memory. Incidentally the address of the function is exactly the function name in C++ syntax. :)
                                          You can use function pointers to call functions, naturally, consider this:

                                          void myCoolFunction(int x)
                                          {
                                          }
                                          
                                          void someOtherFunction
                                          {
                                              void (*functionPointerVariable)(int) = myCoolFunction; // or &myCoolFunction
                                              // Now functionPointerVariable points to the address of myCoolFunction and we can call the function through that ponter
                                              functionPointerVariable(10); // Calls myCoolFunction, equivalent to myCoolFunction(10)
                                          }
                                          

                                          Extending this to classes is somewhat trivial. The main thing to know is that (non-static) methods are the same as regular function, i.e. they reside in the static part of the program memory BUT they need an object to operate on. So one can get a pointer to a method in the same way, only the call is a bit different as you need to bind that function pointer to an object. Rewriting the above examples with member pointers is straightforward:

                                          class A
                                          {
                                              void someMethod(int)
                                              {
                                              }
                                          };
                                          
                                          void someOtherFunction()
                                          {
                                              void (A::*methodPointer)(int) = &A::someMethod; // methodPointer points to the function someMethod of the class A now
                                              A myObject; // We need an object to call the method, so let's create it.
                                          
                                              // Finally we can call the method of myObject with our function pointer. Notice the parentheses around the .* operator, they are required for this because of operator priorities.
                                              (myObject.*methodPointer)(10); // Equivalent to myObject.someMethod(10);
                                          }
                                          

                                          The whole point of this all is that you can store the pointer-to-member variable without actually specifying an object until the very last moment - when the call is done. And this is what Qt does, it stores the pointers and binds the object (with the .* or ->* operator only when the actual call is made.

                                          Read and abide by the Qt Code of Conduct

                                          1 Reply Last reply
                                          3

                                          • Login

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