Important: Please read the Qt Code of Conduct -

Connect QML signal to C++11 lambda slot (Qt 5)

  • Hello everyone,

    New QtQuick user here and having a jolly nice time so far!

    There is one question, however, for which I haven't managed to find the answer so far in the documentation. Imagine that you have a QML object that defines a signal like this:

    @Rect {
    id: bar
    name: "bar"
    signal foo();
    property string baz;

    and you want to connect it to a slot that is not part of a QObject:

    @auto root = qml_container.rootObject(); // returns the Rect defined above
    root->connect(root, "foo()", = { std::cout << "foo!" << std::endl; });@

    Unfortunately, this fails because there is no connect() overload that takes a string signal and a function pointer slot. The new syntax can only take a function pointer signal and function pointer slot:

    @root->connect(root, &SomeQObject::foo, = { /* whatever */ });@

    But the QML signal is not defined as part of a concrete QObject known at compile-time (that's the reason of using QML in the first place!)

    So what I would like to do is access the QML signal by querying the container object at runtime:

    @auto prop = root->property("baz"); // works for properties
    auto sig = root->???("foo"); // what's the correct API for this?@

    From what I can tell so far, if I could somehow get a pointer to the foo QML signal I should be able to connect it to a lambda slot. Does anyone have any ideas?

    (The rationale behind this: clean separation between UI defined in QML and handlers defined in C++. I don't wish to define a QObject for every QML signal if I can somehow avoid it.)

    Question originally asked here:

  • Moderators

    Use the old syntax. That will kill the lambda, but I don't think there is another solution. You might try finding something in QMetaObject but I a quick look tells me it won't help you.

    Or connect in JavaScript.

  • A signal is just a method. You can use the QMetaMethod accessors to find it. isSignal() should return true.
    It's early in the morning and I haven't fully woken up yet, so I might be wrong.


  • Indeed! I can use a QMetaMethod to access the signal at runtime and connect it to a QMetaMethod slot.

    Unfortunately, it's not possible to get a QMetaMethod for a non-QObject slot (so no lambdas or free functions), which means I'm still stuck with the same problem: I cannot connect a QML signal to a lambda slot...

    For the moment, I have developed an ugly workaround where I encapsulate the slot function into a SignalRouter class derived from QObject. This works, but is both in-elegant and a maintenance burden: for every different QML signal signature, I have to add a corresponding C++ signature to the SignalRouter class (huge "container class" smell). Templates might help here but, of course, MOC does not support templated QObjects so this is a no-go.

    I'm starting to think that what I'm trying to do is simply impossible (at least in a clean way) given the current Qt 5 APIs. Does anyone know if Qt 5.1 adds any new functionality regarding signal-slot connections?

  • I really can't answer that, to be honest. Stephen Kelly might know, Thiago certainly would, so you could try asking on #qt on freenode.


  • Few years later, still no QMetaMethod::toSignalFunc(), poor onTheFly us !

    But a solution exists though. You can create a unique slot to create all your QmlToLambda connection instead of roouting each signal trought a C++ declared slot.
    Something like:
    connect(root, qmlSig, this, QMetaMethod::fromSignalFunc(&Interface::myUniqueCppSlotForAllConnections);

    And the implementation for the slot would be something like:
    void Interface::myUniqueCppSlotForAllConnections(QString) {

  • Use the Connections object to connect to a signal on a known C++ object (setContextProperty or similar). Have that signal be connected to your lambda in C++.

    You don't need the Connections object.

    class SignalHolder : public QObject
        void relaySignal(QString msg);
    QQmlApplicationEngine engine;
        SignalHolder sh;
        sh.connect(&sh, &SignalHolder::relaySignal, [](QString msg){
            qDebug() << "relay message:" << msg;
        auto context = engine.rootContext();
        context->setContextProperty("signalholder", &sh);

    In QML:

    Item {
            id: qmlsignalholder
            signal relayMessage(string message)
            Component.onCompleted: {
                relayMessage("Hello Signal")

Log in to reply