Search code examples
qtqmlqtquickcontrols

Using QtCreator 5.3 for Qt Quick UI project, how to link QML button resource to C++ function call


This is my first post on StackOverflow so please excuse any formatting mistakes I might have made.

I'm building a Qt Quick UI project using Qt Quick Controls 1.1 and I have a simple Button in my QML code that I would like to call into my C++ action class. I see a number of examples on this with earlier versions of Qt, but they do not seem to work in 5.3. I chose Qt Quick Controls 1.1 in the project settings. I know this must not be too complicated to do, but I can't seem to find examples using QtCreator 5.3

Here is my main.qml file:

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1

ApplicationWindow {
    id: parentWnd
    visible: true
    width: 640
    height: 480

    Action {
        id: actionSend
        onTriggered: console.log("SEND")
    }

    Button {
        id: send
        text: "Send Request"
        action: actionSend
        signal sendSignal()
    }
}

Here is my main.cpp:

#include <QApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QQmlApplicationEngine engine;

    engine.load(QUrl(QStringLiteral("qrc:///main.qml")));

    return app.exec();
}

Here is the action class where I would like the QML button to call "doSend":

#include<QDebug>
#include<QObject>

class Action : public QObject
{
    Q_OBJECT
public:
    Action();
public slots:
    void doSend();
};

Finally here is my project file:

TEMPLATE = app

QT += qml quick widgets

SOURCES += main.cpp \
    action.cpp

RESOURCES += qml.qrc

# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =

# Default rules for deployment.
include(deployment.pri)

HEADERS += \
    action.h

When I run this, I see the button and I see the logging of "SEND" to the console so I know the QML Action is setup correctly. Any help on how to make the Action call into my action class would be much appreciated!


Solution

  • There are three issues that you're running into here.

    The first is that you haven't registered your Action class with QML in main.cpp:

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
    
        qmlRegisterType<Action>("StevesModule", 1, 0, "Action");
    
        QQmlApplicationEngine engine;
        engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
    
        return app.exec();
    }
    

    The second is that Action is a QML type in the Qt Quick Controls module. It doesn't know anything about your Action class in C++. If you want to use your Action class instead of Qt Quick Controls' Action type, you must import it in your QML file:

    import StevesModule 1.0
    

    The third is that you're not calling the doSend() slot anywhere. You can do this in the onClicked handler of Button:

    import QtQuick 2.2
    import QtQuick.Controls 1.1
    import QtQuick.Layouts 1.1
    import StevesModule 1.0
    
    ApplicationWindow {
        id: parentWnd
        visible: true
        width: 640
        height: 480
    
        Action {
            id: actionSend
        }
    
        Button {
            id: send
            text: "Send Request"
            onClicked: actionSend.doSend()
        }
    }