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

i cannot check my QPushbutton that is in my qtableview



  • Hello, i'm working on a interface using a Qtableview and i put a QPushButton in a QTableView using this :
    QPushButton* H11 = new QPushButton("H1");
    index = m_table_space_pos->index(1,1,QModelIndex());
    ui->tablespacepos->setIndexWidget(index, H11);
    ui->H11->setCheckable(true);
    connect(ui->H11,SIGNAL(clicked()),this,SLOT(on_H11_clicked()));

    the connect is supposed to change the text of the button. the thing is when i click on it nothing happens. thanks to the outputs i made i know that my button IS Checkable, but it doesnt change to true when i click on it. any ideas of where this comes from ?

    thank you in advance.



  • @aftalib said in i cannot check my QPushbutton that is in my qtableview:

    QPushButton* H11 = new QPushButton("H1");
    ui->H11->setCheckable(true);
    

    H11 is a local variable. ui->H11 is something else. How are they the same button?



  • @JonB oh wow thank you, i didnt realize this. i indeed had a button that was also named H11 in my interface and that's why it was misleading.

    so now that i have changed ui->H11 to H11 in my code i see that my button is being checked but the code in the connect does not run


  • Lifetime Qt Champion

    @aftalib said in i cannot check my QPushbutton that is in my qtableview:

    but the code in the connect does not run

    Use the new Qt5 connect syntax (without SGINAL/SLOT macros) to make sure the connect actually succeeded.



  • @aftalib
    Show your code now.



  • here's the code of my connect : 5a3e3da9-fcf0-46ac-a75d-60ec2c01f439-image.png

    @jsulm , this doesnt seem to work : Qt says that clicked() is an undeclared identifier when i take off SIGNAL/SLOT

    my code now runs but only with the last button of the row.i suppose it's because the connect keeps assigning to the next button as the loop goes forward. is there a way to assign the connect() to each button on the loop ?



  • @aftalib said in i cannot check my QPushbutton that is in my qtableview:

    Qt says that clicked() is an undeclared identifier when i take off SIGNAL/SLOT

    You have to read and act on https://wiki.qt.io/New_Signal_Slot_Syntax.

    here's the code of my connect

    You show no connect() statement. You show your proposed slot code instead.



  • @JonB sorry, here's my connect() : d21ee820-b557-4b71-84f2-49c37338c200-image.png

    thank you, i'm going to read this



  • @aftalib
    Earlier I only see:

    index = m_table_space_pos->index(1,1,QModelIndex());
    

    I do not see where you are creating QPushButtons in a loop, putting each one into the table, and connecting each one to the slot. I see you only addressing (1, 1) in the table.

    Further, the slot only looks at one H11 variable. I do not know how that H11 relates to each of the push buttons you created.

    If you seem to intend AntArrayDialog::on_H11_clicked() slot to handle any of the buttons pressed (connect()ed to each one), it is going to need to know which button was clicked. And that will require you to use a C++ lambda for the connection, to pass which button was clicked as a parameter to the slot....

    Start by just verifying your slot gets called for any button clicked, not just one button....



  • @JonB my bad i hadnt updated my code at the time because i was doing tests to see if it was working for one button but i replaced (1,1) with (1,i) so i indeed have a row of buttons.
    my slot gets called for the last button that is in the row of my TableView

    i'm going to see about the C++ lambda you're talking about, it might be the solution i was looking for



  • so C++ lambda might be the way to relate to each of the QPushButtons i created with my loop ?



  • @aftalib
    You will need the lambda when you are ready to have the single slot code method handle the clicking of any of the push buttons, which I suspect is what you will want to achieve.

    However, before you do that, put a qDebug() << "clicked" in as the first statement in the slot. Verify that gets called when any of the buttons you created are clicked, not just one button. Only at that point are you ready to move to a lambda for the slot which will pass which button was pressed as a parameter to the slot....



  • @JonB okay, the slot gets called of any of the buttons i have created, i have the "clicked" output on each of the buttons



  • @aftalib
    And have you used the new style syntax I referred you to earlier? Show your connect() statement now.



  • @JonB i dont think i got it right.. the IDE still says that clicked() is an undeclared identifier.. 5d0c7d30-3cdf-4f64-a2c0-8429bc0d725f-image.png



  • @aftalib
    I said to you earlier:

    You have to read and act on https://wiki.qt.io/New_Signal_Slot_Syntax.

    but you do not seem to have done anything about this....



  • @JonB no i did check this in order to do the new connect statement but i dont get how am i supposed to write this with what is written on this page


  • Lifetime Qt Champion

    @aftalib Please post text not screen shots.

    connect(H11, &QPushButton::clicked, this, &WHAT_EVER_THIS_TYPE_IS::on_H11_clicked);
    


  • @aftalib
    The very first section there shows an example of changing from SIGNAL/SLOT() macros

    connect(
        sender, SIGNAL( valueChanged( QString, QString ) ),
        receiver, SLOT( updateValue( QString ) )
    );
    

    over to

    connect(
        sender, &Sender::valueChanged,
        receiver, &Receiver::updateValue
    );
    

    The code you have pasted does not attempt to follow that required pattern.



  • okay thats my bad i didnt quite understand the syntax that was written in the new connect statement but i think i got it now, thank you. here's what i wrote :

             connect(H11, &QPushButton::clicked,this,&AntArrayDialog::on_H11_clicked);
    
    

    i dont get any errors and the program launches well



  • then i have to use lambda with this syntax in order for my slot to work with any of the buttons i created right?



  • @aftalib
    Yes, this is good :)

    Now, I believe, since (I assume) you will have each of the buttons connect to this one slot method, you will want the slot to receive a parameter to tell it which particular button was clicked this time to call the slot, right?

    To do that you are going to need to move on to connect()ing a C++ lambda instead of the slot function as you currently do now. Then a parameter can be added, so that the signal will pass it to the slot. the parameter will identify which button emitted the signal.

    That new-style syntax page includes the following example:

    Can be used with C++11 lambda expressions:

    connect(
        sender, &Sender::valueChanged,
        [=]( const QString &newValue ) { receiver->updateValue( "senderValue", newValue ); }
    );
    

    The lambda bit is:

    [...](...) { ... }
    

    See if you can figure how to pass the QPushButton * object from the signalling push button to the slot....



  • @JonB okay, just before you answered i tried this :

    connect(H11, &QPushButton::clicked,[this](){
    
                 if (H11->isChecked()) {
    
                     H11->setText("H2");
                     qDebug() << "test";
                 }
    
                 else if (H11->isChecked()==false){
                     H11->setText("H1");
    
    
                 }
    
             });
    

    so if i click on any button i want it to change to H2, then to H1 if i reclick on it and so on..
    i didnt get any errors but it didnt work so im assuming this is wrong. im gonna retry something else with what you said



  • @aftalib
    At least you have you lambda syntax correct, that is good!

    Your connect() is not attempting to pass which button was clicked, as a parameter to the slot. The slot only references whatever one button this->H11 currently refers to when it is executed. If you are wanting the slot to know which button invoked it in order to do its work, you are going to need that as a parameter to the slot in the lambda.



  • @JonB said in i cannot check my QPushbutton that is in my qtableview:

    okay i get what you're saying, so i need to put the button that is calling the slot as a parameter. here's what i tried but its not working either :

     connect(H11, &QPushButton::clicked,[=](QPushButton &button){
    
                 if (button.isChecked()) {
    
                     button.setText("H2");
                     qDebug() << "test";
                 }
    
                 else if (button.isChecked()==false){
                    button.setText("H1");
    
    
                 }
    
             });
    

    i know that its almost the right thing but im missing something



  • so i've spent most of the last night searching for a solution to this but still havent found. does anyone have an idea about this ?

    thank you in advance



  • @aftalib
    One way, briefly, untested:

    connect(button1, &QPushButton::clicked, [=, button1]() { pushbutton_clicked(button1); }
    connect(button2, &QPushButton::clicked, [=, button2]() { pushbutton_clicked(button2); }
    for (auto button : each_button_when_created)
        connect(button, &QPushButton::clicked, [=, button]() { pushbutton_clicked(button); }
    
    void ThisClass::pushbutton_clicked(QPushButton &button)
    {
        // now button parameter is whichever button clicked
        // so you can use this for stuff you want to do on any of the buttons
        if (button.isChecked())
            ...
    }
    


  • okay i can see this working, so i have to put the numbers of buttons i want in the line "for (auto button : each_button_when_created" ? i dont get how this line works



  • i just checked how the for auto loop works. would it help if i created an array of buttons in order for this to run ?



  • @aftalib
    Yes, but you are taking the code too literally. It doesn't matter whether you use a for on an array of buttons or whatever. In your original code I believe you have some loop which creates QPushButtons dynamically --- I assume/was assuming you create one per each some column in your QTableView? Anyway that loop is there to show you that you can connect() any time you have a dynamic pushbutton to link up, wherever it coms from, or individual button variables button1/2 if that's what you have.



  • @JonB okay i see what you mean, so here's what i did my code, but i have some problems :

     for (int i=0; i<nbOfAnt/2; i++) {
                 QPushButton *button = new QPushButton("H1");
                 index = m_table_space_pos->index(1,i,QModelIndex());
                 ui->tablespacepos->setIndexWidget(index, button);
                 button->setCheckable(true);
                     connect(button, &QPushButton::clicked, [=, button]() { on_H11_clicked(button); }
    
        );}
    

    the code cant run because the button argument in [=, button] must be captured with & and the argument in my slot doesnt work either. i have to use *button. but if i do so my program crashes..

    note : nbOfAnt is a dynamic int that changes with the will of the user and will also determine the number of buttons in the qtableview



  • it works ! i figured out myself :

    for (int i=0; i<nbOfAnt/2; i++) {
                 QPushButton *button = new QPushButton("H1");
                 index = m_table_space_pos->index(1,i,QModelIndex());
                 ui->tablespacepos->setIndexWidget(index, button);
                 button->setCheckable(true);
                     connect(button, &QPushButton::clicked, [&,button,this]() { on_H11_clicked(*button); }
    
        );}
    

    putting a 3rd argument in the connect resolved my problem. thank you for your time @JonB


Log in to reply