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

QToolButton clicked signal emitted several times



  • Hi guys, I am facing a problem that I don't really understand.
    Here is my code :

    void TabPhotos::addItem(QPixmap pix, QString title, QString comment){
    
        pix = pix.scaled(QSize(1356, 842), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QLabel* label = new QLabel();
    
        label->setPixmap(pix);
        label->setAlignment(Qt::AlignCenter);
    
        ui->stackedWidget_photos->addWidget(label);
        _commentaires.append(comment);
    
        _titres.append(title);
    
        QToolButton* button = new QToolButton;
        button->setCheckable(true);
        QIcon *ico = new QIcon();
        ico->addPixmap(QPixmap(":/icones/images/bouton-check-vert.png"),QIcon::Normal,QIcon::On);
        ico->addPixmap(QPixmap(":/icones/images/bouton-check-vide.png"),QIcon::Normal,QIcon::Off);
        button->setIcon(*ico);
        button->setIconSize(QSize(50, 50));
        ui->gridLayout_buttons->addWidget(button,0, ui->gridLayout_buttons->columnCount());
        connect(button, SIGNAL(clicked()), this, SLOT(showPhoto()));
    }
    

    As you can see, in this function addItem(), I add a QPixmap in a QStackWidget through a QLabeL. In order to navigate between items, each item has its QToolButton corresponding. So when I click on a QToolButton, I want the program to show the good widget in the QStackedWidget (I want to show the good picture).

    It works very well when I have 1 or 2 items. BUT, when I have 3, 4, 5... items (so 3, 4, 5... QToolButtons), when I click on one of the buttons, the clicked signal is emitted more than one time :

    • 3 buttons : clicked signal emitted twice.
    • 4 buttons : clicked signal emitted 3 times.
    • 5 buttons : clicked signal emitted 4 times.

    Like if buttons were the exact same object.

    Can anybody knows what happened here and how to fix that issue ?

    Thank you !


  • Moderators

    @Match0um

    1. your qicon instance leaks in memory (dont create it on the heap)
    2. you add your buttons always on the same position? (row: 0, column: gridLayout->columnCount())


  • @raven-worx said in QToolButton clicked signal emitted several times:

    dont create it on the heap

    Thank you for your answer !

    1. Ok so for the icon, I put that in the class constructor :
    _iconButton = new QIcon();
    _iconButton->addPixmap(QPixmap(":/icones/images/bouton-check-vert.png"),QIcon::Normal,QIcon::On);
    _iconButton->addPixmap(QPixmap(":/icones/images/bouton-check-vide.png"),QIcon::Normal,QIcon::Off);
    

    And how I did in the addItem() function :

    button->setIcon(*_iconButton);
    

    But it doesn't change anything.

    1. Yes, the button is always added at the position (row: 0, column: gridLayout->columnCount()) of the gridLayout. But when a button is added, the gridLayout->columnCount() is incremented because for each item added in a gridLayout row, the column count should be incremeted.

  • Moderators

    @Match0um
    ad 1) you are not supposed to use new QIcon (heap/pointer) but just create it on the stack (QIcon())

    what does your showPhoto() method do? How does this slot know what photo show when each button calls the same slot?



  • @raven-worx
    Ok thank you for the precision !

    Here is the showPhoto() method :

    void TabPhotos::showPhoto(){
    
        qDebug("ShowPhoto");
        QToolButton* button = qobject_cast<QToolButton*>(sender());
        button->blockSignals(true);
    
        ui->textEdit_commentaire->blockSignals(true);
        ui->lineEdit_titre->blockSignals(true);
        int index = ui->gridLayout_buttons->indexOf(button)-2;
        int old_index = ui->stackedWidget_photos->currentIndex();
        ui->stackedWidget_photos->setCurrentIndex(index);
    
        for(int i = 2; i<ui->gridLayout_buttons->columnCount()-2; i++){
            QToolButton* b = static_cast<QToolButton*>(ui->gridLayout_buttons->itemAt(i)->widget());
            if(i!=index+2){
                b->setChecked(false);
                qDebug()<<"emet signal";
                emit askChangePage(old_index);
                ui->label_titre->setText(_titres[index]);
                ui->lineEdit_titre->setText(_titres[index]);
                ui->label_commantaire->setText(_commentaires[index]);
                ui->textEdit_commentaire->setText(_commentaires[index]);
            }else{
                b->setChecked(true);
            }
        }
    
        ui->textEdit_commentaire->blockSignals(false);
        ui->lineEdit_titre->blockSignals(false);
    
        button->blockSignals(false);
    }
    

    How it looks like visually :
    imageQt.png

    When you click on a button below, it shows the corresponding picture, title, and comment.


  • Lifetime Qt Champion

    Hi,

    Do you have any other connect statement in your code ? Or something else that calls that slot ?



  • @SGaist Hi, this slot is called only in this connect statement in the addItem() method :
    connect(button, SIGNAL(clicked()), this, SLOT(showPhoto()));
    after creating the button.
    The method addItem() is called several times (so several buttons are created and the connect statement is called several times too).


  • Lifetime Qt Champion

    Then please provide a minimal, compilable example so we can reproduce the issue.



  • @Match0um What is meant by

    when I click on one of the buttons, the clicked signal is emitted more than one time
    

    Does on click of single button it prints "ShowPhoto" debug message more than once?
    or
    Are you taking about the "emet signal" debug message in the slot? which is printed multiple times?



  • @nagesh Hi, I mean that it prints "ShowPhoto" debug message more than once AND "emet signal" the same number of times. So it means that the slot showPhoto() is called several times. BUT it is only connected to the signal clicked() of each button of the UI. I ensure that this slot is not called somewhere else.

    I tried to make a minimal example in order to provide something with the same behavior that you can test guys. But I am not able to reproduce the same issue, everything works well in my "minimal" example project. So I guess that the issue comes from the "big" project I am working on.

    But I am a bit lost, the problematic slot showPhoto() is only connected to the buttons and is not called somewhere else in the code. It is like if the buttons where actually the same, or maybe a pointer issue.


  • Lifetime Qt Champion

    Then reduce your code until the issue disappears or it's so minimal that we can take a look on it. Daily work for a programmer... :)



  • @Match0um In showPhoto Comment remainig code and check with only debug message.
    This might give you the clue

    void TabPhotos::showPhoto(){
    qDebug("ShowPhoto");
    }
    


  • Hi guys, it's been a while but I found the issue. As my signal was on a loop, it was emitted each time the program went on the loop. I don't know why I didn't see that sorry for that. The topic is now closed.


Log in to reply