Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QList / QPushbutton and connect/slot features



  • I have recently created a list of QPushbuttons as follows:

    H file:
    QList < QList <QPushButton *>> buttons_per_session;
    QList < QPushButton *> buttons_per_tab;

    Cpp file:

         for (qint16 i=0; i <= total; i++)
                       {
                            buttons_per_tab.append(new QPushButton);
                       }
    
         grid_per_session.append(grid_per_tab);
    

    and everything is working fine

    but now I would like to connect these buttons to an action as follows:

    connect(buttons_per_session[x][y], SIGNAL(clicked()),this, SLOT(changeColor()));

    My concern is how can I get x & y (QList indices) from a clicked button?

    Thks for your usual coop



  • J.Hilk

    I used your last solution ans it's working fine

    Thks for your help



  • in changeColor() slot, you can use sender() to get the QPushButton instance which generates to signal.

    You can do something like this:

    for(int idx = 0; idx < grid_per_session.size(); ++idx)
    {
          int pos = grid_per_session.at(idx).indexOf(sender());
         if (pos >=0 )
         {
             // found !
         }
    }
    

    Regards

    Fabrice


  • Moderators

    hi @jipe3001

    do you really need that indices after you populated the list? why don't you make the connect during QPushButton creation ?

     for (qint16 i=0; i <= total; i++)
                       {
                           QPushButton *btn = new QPushButton();
                           connect(btn, SIGNAL(clicked()),this, SLOT(changeColor()));
                            buttons_per_tab.append(new QPushButton);
                       }
    
         grid_per_session.append(grid_per_tab);
    
    

    or if you really want to do this afterwards:

    for(List<QPushButton *> &list : buttons_per_tab)
          for (QPushButton *btn : list)
                 connect(btn, SIGNAL(clicked()),this, SLOT(changeColor()));
    


  • CORRECTED VERSION

    I have recently created a list of QPushbuttons as follows:

    H file:
    QList < QList <QPushButton *>> buttons_per_session;
    QList < QPushButton *> buttons_per_tab;

    Cpp file:

     for (qint16 i=0; i <= total; i++)
                   {
                        buttons_per_tab.append(new QPushButton);
                   }
    
     buttons_per_session.append(buttons_per_tab);
    

    and everything is working fine

    but now I would like to connect these buttons to an action as follows:

               connect(buttons_per_session[x][y], SIGNAL(clicked()),this, SLOT(changeColor()));
    

    My concern is how can I get x & y (QList indices) from a clicked button?

    Thks for your usual coop



  • @jipe3001: you want to get (X,Y) in the called slot? Right?
    So you can use sender() to got the instance which emit the signal

    IMPORTANT: to be able to use sender() you must force QueuedConnection!

    ...
    connect(buttons_per_session[x][y], &QPushButton::clicked, this, &MyClass::changeColor, Qt::QueuedConnection);
    
    ...
    void MyClass::changeColor()
    {
        auto* btn =qobject_cast<QPushButton*>(sender());
        if (!btn)
            return;
    
        for(int idx = 0; idx < grid_per_session.size(); ++idx)
        {
             int pos = grid_per_session.at(idx).indexOf(btn);
             if (pos >=0 )
             {
                 // sender() == grid_per_session[idx][pos]
             }
        }
    }
    

  • Moderators

    I may have miss read your question.

    I would however discourage the use of sender() as it n violates the object-oriented principle of modularity.

    The recommended way is to use QSignalMapper

    But since Qt5 also supports the use of lambdas inside connects, that is also a valid option:

    connect(btn, &QPushButton::clicked,this, [=]()->void{changeColor(i,j);});
    

    with i and j as parameter of your slot.


  • Lifetime Qt Champion

    @KroMignon said in QList / QPushbutton and connect/slot features:

    IMPORTANT: to be able to use sender() you must force QueuedConnection!

    That's completely wrong. Why would you need that ?



  • @SGaist , not completely wrong, just a little bit ;-)
    In fact, the only thing to carry on, is that DirectConnection is not used when the slot is not in same thread as emitter.
    So forcing QueuedConnection will ensure this will never happen.


  • Lifetime Qt Champion

    @KroMignon said in QList / QPushbutton and connect/slot features:

    @SGaist , not completely wrong, just a little bit ;-)

    No, it is completely wrong, sender's usage does not depend on the type of connection.

    In fact, the only thing to carry on, is that DirectConnection is not used when the slot is not in same thread as emitter.

    That part is correct.

    So forcing QueuedConnection will ensure this will never happen.

    And why would you need to force that for everything ?



  • @SGaist said in QList / QPushbutton and connect/slot features:

    No, it is completely wrong, sender's usage does not depend on the type of connection.

    Okay, your right, QueuedConnection is not required. My mistake.



  • Thks for all your answers but I am getting a bit confused with the various solutions suggested.

    To be clear :

    I am creating a various list of QPushbutttons using this structure:

             QList < QList <QPushButton *>> buttons_per_session;
             QList < QPushButton *> buttons_per_tab;
    

    I therefore is interested in creating an action for each QPushbutton

    Of course I can generate a connect statement when creating each QPushButton but
    this may end with hundreds of connect lines (number not known and dependent of the opened file)
    which does not seem to be very elegant and memory consuming.

    To avoid this I am looking for a solution for which I can determine which QPushButton has been clicked
    and send these parameters to the slot.

    The solution below seems to be fine to send the parameters (i,j) to the changeColor slot
    .
    connect(btn, &QPushButton::clicked,this, =->void{changeColor(i,j);});

    but I cant figure out how these parameters are determined, btn does not seems to be part of my QList structure

    Tks for your support


  • Moderators

    @jipe3001

    untested, beware of typos.

    QList < QList <QPushButton *>> buttons_per_session;
    for( int i(0); i< 10; i ++) {
          QList < QPushButton *> buttons_per_tab;
          for(int j(0); j < 10; j++) {
                  QPushButton *btn = new QPushButton();
                  connect(btn, &QPushButton::clicked,this, [=]()->void{changeColor(i,j);});
                  buttons_per_tab.append(btn);
          }
          buttons_per_session.append(buttons_per_tab);
          
    }
             
    

    [edit: fixed small mistake SGaist]



  • J.Hilk

    I used your last solution ans it's working fine

    Thks for your help


Log in to reply