Connecting a Qt Quick Controls signal to a C++ slot



  • Hello,

    I'm new to Qt, so bear with me on this one.

    I have a very simple toy app which consists of a Qt Quick Controls interface and a C++ backend. All the app does is display a table of data from the C++ app (a list of custom QObjects). It should be able to load and save data in the table via the C++ backend.

    Eventually, I figured out that to make the model accessible from QML I needed to add a method to extract the QQmlContext object from the QtQuick2ControlsApplicationViewer. I did, and called this method rootContext. From there, I was able to make the data accessible by:

    @
    QQmlContext *context = viewer.rootContext();
    context->setContextProperty("holeModel", QVariant::fromValue(holeList));
    @

    Where holeList is my QList of objects following my data model. So far, so good - the table displays the data.

    Now, I want to implement the ability to save from the GUI. So, logically I will want to connect a signal from one of my Qt Quick Controls to one of my C++ classes. I've been at it all day with no success.

    Every example I've found seems to extract the root object from whichever viewing engine is used. The trouble is, I can't get this out of QtQuick2ControlsApplicationViewer and indeed I can't even seem to find it in any of the objects which are private to QtQuick2ControlsApplicationViewer.

    My QML code is:

    @
    ApplicationWindow {
    id: applicationWindow1
    title: qsTr("Holefield Editor Demo")
    width: 960
    height: 540

    /* ... a bunch of stuff that's not interesting snipped ... */

    FileDialog {
        signal saveSignal (string path)
    
        id: saveDialog
        title: "Save as..."
        selectExisting: false
        selectMultiple: false
        onAccepted: {
            saveSignal(saveDialog.fileUrl)
        }
        Component.onCompleted: visible = false;
    }
    

    /... more stuff snipped .../

    }

    @

    I have tried connecting the signal to the slot in such ways as:

    @
    QQmlContext *context = viewer.rootContext();

    QQmlContext::connect(context->findChild<QObject*>(QString("saveDialog")), SIGNAL(saveSignal(QString)), fileOps, SLOT(saveFile(QString)));
    @

    and

    @
    QQmlContext *context = viewer.rootContext();

    QObject::connect(context, SIGNAL(saveSignal(QString)), fileOps, SLOT(saveFile(QString)));
    @

    Where fileOps.saveFile is a slot which saves the loaded model to a CSV file. None of these options work. How would I go about properly connecting a QtQuickControls signal to a C++ slot, and vice-versa?



  • Hi, there are many ways of doing what you want, so I can just tell your how I would do this in your case.
    Instead of connecting a QML signal to a c++ slot I usually just call the c++ slot from c++ (without any connections), that of course depends on your c++ file but you can easily register any QObject with the QML engine and then create objects of the class form QML and also call slots and any function marked with Q_INVOKEABLE.

    So in your case you don't need to use the QQmlContext or anything from the QtQuick2ApplicationViewer or whatever, but you just register your model class to the QML engine and then create the model object from QML, so you can have a "save" slot in the model (if that makes sense) and just call it.

    to register any QObject class to the QML engine you can simply use "qmlRegisterType":http://qt-project.org/doc/qt-5.0/qtqml/qqmlengine.html#qmlRegisterType in your main.cpp (before the QML engine is created, even be before QGuiApplication):
    @
    qmlRegisterType<YourModelClass>("YourModel", 1, 0, "YourModel");
    @
    and then create an object anywhere in QML with:
    @
    import YourModel 1.0

    YourModel {
    id: model
    }

    // in some QML function
    model.save()
    @
    give it an ID like any other QML object and you can access it and call slots (and invokable methods), connect signals and use it as your model in the ListView (via the ID reference).

    If you want you can still create the model form c++ and use setContextProperty, if you have registered the class your should be able to invoke the slots on that object from QML but I think creating the model in QML is cleaner instead of a global context property?

    I hope that helps you, there might be some official tutorials on this, but this should get you started. :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.