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

How to find sender in slot?



  • Hi,

    I display a number of Checkboxes that get created in a loop and connected to a method like:

    foreach(...) {
        box = DlgEnChckBxCrt("Enable", (Qt::CheckState)sttngs->value(grp+"/Enable").toInt());
        bool rv = QObject::connect(this->box, &QCheckBox::clicked, [&] { this->DlgEnChckSv(); });
    }
    QCheckBox* scaper::DlgEnChckBxCrt(QString txt,Qt::CheckState chckd) {
            QCheckBox *box = new QCheckBox(txt);
            box->setCheckState(chckd);
            return box;
    }
    

    Now in DlgEnChckSv I need to figure out, which checkbox got clicked, I have tried the following which has failed:

    void scaper::DlgEnChckSv(void) {
        QCheckBox *src = qobject_cast<QCheckBox*>(sender());
        if (src)
            dbg_prnt << "inside " << __func__ << " for " << src->text().toStdString() << std::endl;
        else
            dbg_prnt << "no object found" << std::endl;
    }
    

    Why does this not work as expected and how do I do it correctly?
    Thank you!


  • Qt Champions 2017

    Just check this post



  • Okay,

    So I've figured out that I need to use a variable in the current stack scope to work with lambda, i.e. I got it working with something like:

    QCheckBox *tmpbox = nullptr;
    foreach(...) {
        box = DlgEnChckBxCrt("Enable", (Qt::CheckState)sttngs->value(grp+"/Enable").toInt());
        tmpbox = box;
        bool rv = QObject::connect(this->box, &QCheckBox::clicked, [tmpbox,this] { this->DlgEnChckSv(); ;dbg_prnt << "senderObject: " << tmpbox->text().toStdString() str.toStdString() << std::endl;});
    }
    

    But I'm now wondering how I can distinguish them from each other as they all have the same label "Enable", I need to diustinguish them by grp how would I do so?

    I tried tmpbox->name() but that doesn't work...


  • Lifetime Qt Champion



  • What about it saying:
    This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code. ?
    I guess using lambda is its replacement, by passing the string text directly to the slot as argument - I thought I read that this shouldn't be done somewhere else... (missing the reerence)

    ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
        : QWidget(parent)
    {
        QGridLayout *gridLayout = new QGridLayout;
        for (int i = 0; i < texts.size(); ++i) {
            QString text = texts[i];
            QPushButton *button = new QPushButton(text);
            connect(button, &QPushButton::clicked, [=] { clicked(text); });
            gridLayout->addWidget(button, i / 3, i % 3);
        }
        setLayout(gridLayout);
    }
    ```

  • Lifetime Qt Champion

    @cerr This is the answer: "This class was mostly useful before lambda functions could be used as slots." :-)
    Use lambda functions as you already do.

    "I need to diustinguish them by grp" - what is grp?
    "I tried tmpbox->name() but that doesn't work..." - did you set names before?



  • @jsulm said in How to find sender in slot?:

    @cerr This is the answer: "This class was mostly useful before lambda functions could be used as slots." :-)

    Yup,

    I've figured this out by now as well. I'm still new to Lambda and am learning as I go...!

    Use lambda functions as you already do.

    "I need to diustinguish them by grp" - what is grp?

    grp is a string that I used above in sttngs->value(grp+"/Enable") - that's how I distinguish the "Enables" from each other

    "I tried tmpbox->name() but that doesn't work..." - did you set names before?

    No I had not but it would give me a compiler error: ‘class QCheckBox’ has no member named ‘name’ after I had tried to access it with box->name()

    Got it working fine now! Thanks for your help! :)



  • @julm I still have another question my friend, I did not get it working entirely the way I intended:
    When I create my buttons in this fashion:

    foreach(const QStringList  grp, groups) {
        box = DlgEnChckBxCrt("Enable", (Qt::CheckState)sttngs->value(grp+"/Enable").toInt());
        tmpbox = box;
        bool rv = QObject::connect(this->box, &QCheckBox::clicked, [tmpbox,this] { this->DlgEnChckSv(); ;dbg_prnt << "senderObject: " << tmpbox->text().toStdString() str.toStdString() << std::endl;});
    }
    

    grp will be a different value in every iteration as it calls the DlgEnChckBxCrt() function to create the QCheckBoxes but when a click triggers the lambda function in the connect() clause, grp will always just be the last value in the QStringList groups. So my question is, can I statically create the connect() linkage at the time QCheckBoxes get created too or how would I best go about this to have a connect for each value of grp?



  • I continue this in a new thread, the original problem has been resolved!
    link to continuing thread: https://forum.qt.io/topic/105642/cn-i-find-the-layout-a-given-widget-is-a-member-of


Log in to reply