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

QObject::connect: signal not found in promoted widget with Lambda syntax



  • I have an overloaded QTreeWidget class, with my SIGNALS: I have promoted it in my UI and when I listen promoted QTreeWidget object with a lambda syntax I have an error.

    QObject::connect: signal not found in CustomTreeWidget.
    

    MY CustomTreeWidget looks like:

    .h

    class CustomTreeWidget : public QTreeWidget
    {
        Q_OBJECT
    public:
        explicit CustomTreeWidget(QWidget *parent = 0);
    
        ~CustomTreeWidget() {
        }
    
    signals:
        void currentNodeChanged(QSet<int> uids);
        void deleteRequest(QVector<int> uids);
    }
    

    .cpp

    CustomTreeWidget::CustomTreeWidget(QWidget *parent) : QTreeWidget(parent)
    {
        setAnimated(true);
    
        connect(this, &CustomTreeWidget::customContextMenuRequested, this, [=](const QPoint &pos) {
            this->m_bCustomMenuOpen = true;
            const auto &&item = this->itemAt(pos);
    
            QMenu myMenu;
    
            bool ok = !(item) ? false : true;
    
            if (ok) {
            //თუ topLevelItem -ია მხოლოდ დამატების action -ი უნდა იყოს ჩართული.
                if (item == this->topLevelItem(0) || item == this->topLevelItem(0)->child(0)) {
                    ok = false;
                }
            }
    
            QAction *Removecnt = myMenu.addAction(tr("&წაშლა"), this, SLOT(DeleteNode()));
            Removecnt->setIcon(QIcon(":/global_res/delete.png"));
            Removecnt->setEnabled(ok);
    
            myMenu.exec(this->mapToGlobal(pos));
        });
    }
    
    void CustomTreeWidget::BFS(QTreeWidgetItem *item, QSet<int> &out)
    {
        std::queue<QTreeWidgetItem *> Q;
        Q.push(item);
    
        while (!Q.empty()) {
            QTreeWidgetItem *now = Q.front(); Q.pop();
            out.insert(this->m_mapUids[now]);
            for (int i = 0; i < now->childCount(); i++) {
                Q.push(now->child(i));
            }
        }
    }
    
    QSet<int> CustomTreeWidget::GetCurrentNodeUids()
    {
        QSet<int> uids;
        if (!this->currentItem())
            return uids;
    
        this->BFS(this->currentItem(), uids);
        return uids;
    }
    
    void CustomTreeWidget::DeleteNode()
    {
        QSet<int> nodes = this->GetCurrentNodeUids();
        QVector<int> uids;
        for (auto it : nodes) {
            uids.push_back(it);
        }
    
        emit deleteRequest(uids);
    }
    

    My lambda looks like:

    connect(ui->productTree, &CustomTreeWidget::deleteRequest, this, [=](QVector<int> uids) {
        //logic
    });
    

    But this signal works with old syntax.

    connect(ui->productTree, SIGNAL(deleteRequest(QVector<int>)), this, SLOT(checkSlot(QVector<int>)));
    

    And this slot is.

    void ProductForm::checkSlot(QVector<int> uids)
    {
        qDebug() << uids.size();
    }
    

    So what is problem lambda syntax?



  • Did you include the header of CustomTreeWidget in the ProductForm source file?



  • @VRonin
    Yes i have.



  • There's nothing wrong in the code you posted, they only thing I can think of is try using QOverload<>::of in case that's the source of the problem



  • @VRonin
    Something like this?

    connect(ui->productTree, static_cast<void (CustomTreeWidget::*)(QVector<int>)>(&CustomTreeWidget::deleteRequest), this, [=](QVector<int> uids) {
        qDebug() << "yeapp";
    });
    

    or

    connect(ui->productTree, QOverload<QVector<int>>::of(&CustomTreeWidget::deleteRequest), this, [=](QVector<int> uids) {
        qDebug() << "yeapp";
    });
    

    Everything is same.


  • Moderators

    Quick test: Create a dummy class that inherits QObject (not a promoted QWidget!) and also give it a signal void deleteRequest(QVector<int> uids). Instantiate this dummy class and try to connect this dummy signal to your lambda.

    Does it work?



  • Guys... I dont know why but my CustomTreeWidget class have a UI. Should it be? :D


  • Lifetime Qt Champion

    @Taz742 said in QObject::connect: signal not found in promoted widget with Lambda syntax:

    I dont know why but my CustomTreeWidget class have a UI

    What do you mean? It is a GUI class, so it has a UI. Or do you mean it has ui member variable?


  • Moderators

    Hi,
    have you registered QVector as a metatype - using qRegisterMetaType, to use it via Signal/Slots?



  • @J.Hilk
    In main.cpp

        qRegisterMetaType<QVector<int>>("QVector<int>");
    

    Now i am tryng but have a same situation.


  • Lifetime Qt Champion

    Hi,

    here's a dummy example:

    #include <QtCore>
    #include <QtDebug>
    
    class MyClass : public QObject
    {
        Q_OBJECT
    
    signals:
        void deleteRequest(QVector<int> uids);
        void done();
    
    public slots:
        void trigger()
        {
            emit deleteRequest(QVector<int>{1, 2, 3, 4});
            QTimer::singleShot(1000, this, &MyClass::done);
        }
    };
    
    int main(int argc, char** argv)
    {
        QCoreApplication app(argc, argv);
    
        MyClass mc;
        QTimer::singleShot(1000, &mc, &MyClass::trigger);
        QObject::connect(&mc, &MyClass::done, qApp, &QCoreApplication::quit);
        QObject::connect(&mc, &MyClass::deleteRequest, [](const QVector<int>& data) { qDebug() << data; });
        return app.exec();
    }
    
    #include "main.moc"
    

    The content of the QVector is printed after one second and the application ends after another one. Does it work on your machine ?



  • @SGaist
    Yes its work. I am also tryed to create new project, move my CustomTreeWidget and work there.



  • @SGaist
    I have a same situation in other class.
    Can you check this example?

    #ifndef IMAGEWORKER_H
    #define IMAGEWORKER_H
    
    #include <QObject>
    #include "QDebug"
    #include "globalhelper.h"
    #include "QThread"
    #include "QMutex"
    #include "QFile"
    #include "QDir"
    #include "QCryptographicHash"
    #include "QByteArray"
    
    class ImageWorker : public QObject
    {
        Q_OBJECT
    public:
        explicit ImageWorker(QObject *parent = 0) {
            Q_UNUSED(parent);
            QThread *thread = new QThread;
            this->moveToThread(thread);
            connect(thread, &QThread::started, this, &ImageWorker::doWork);
            connect(this, &ImageWorker::finished, thread, &QThread::quit);
            connect(this, &ImageWorker::finished, this, &ImageWorker::deleteLater);
            connect(thread, &QThread::finished, thread, &QThread::deleteLater);
            thread->start();
        }
    
        ~ImageWorker() {
            qDebug() << "ImageWorker deleted";
        }
    
    signals:
        void finished();
    
    public slots:
        void doWork() {
            emit finished();
        }
    
    private:
        bool compareImages(const QByteArray &myImage, const QByteArray &serverImage) const
        {
            return myImage.toHex() == serverImage.toHex();
        }
    
        QByteArray fileChecksum(const QByteArray &bytes, QCryptographicHash::Algorithm hashAlgorithm = QCryptographicHash::Md5) const
        {
            QCryptographicHash hash(hashAlgorithm);
            hash.addData(bytes);
            return hash.result();
        }
    
    };
    
    
    #endif // IMAGEWORKER_H
    
    

  • Lifetime Qt Champion

    Since you implement the constructor in your derived class, why don't you call the base class constructor ?

    What exact situation do you have ?



  • @SGaist said in QObject::connect: signal not found in promoted widget with Lambda syntax:

    Since you implement the constructor in your derived class, why don't you call the base class constructor ?

    I dont understood...

    @SGaist said in QObject::connect: signal not found in promoted widget with Lambda syntax:

    What exact situation do you have ?

    QObject::connect: signal not found in ImageWorker
    QObject::connect: signal not found in ImageWorker
    

    I am debuging it and its happen here:

            connect(this, &ImageWorker::finished, thread, &QThread::quit);
            connect(this, &ImageWorker::finished, this, &ImageWorker::deleteLater);
    

  • Lifetime Qt Champion

    explicit ImageWorker(QObject *parent = 0)
            : QObject(parent)
        {
            QThread *thread = new QThread;
           etc.
    

    I removed #include "globalhelper.h" and it build successfully on macOS.



  • @SGaist
    There is great uncertainty... I changed

    @Taz742 said in QObject::connect: signal not found in promoted widget with Lambda syntax:

        connect(this, &ImageWorker::finished, thread, &QThread::quit);
        connect(this, &ImageWorker::finished, this, &ImageWorker::deleteLater);
    

    to

            connect(this, SIGNAL(workerFinished()), thread, SLOT(quit()));
            connect(this, SIGNAL(workerFinished()), this, SLOT(deleteLater()));
    

    its work...


Log in to reply