Integrating QtQuick with c++ code



  • Hello,

    I'm new to Qt, and I'm having trouble integrating c++ with QtQuick

    When I call the next button, I want to display the text "test123" in the block TextArea from c++.

    Here's the code I have:

    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();
    

    }

    main.qml:
    import QtQuick 2.5
    import QtQuick.Controls 1.4
    import QtQuick.Dialogs 1.2

    ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }
    
    MainForm {
        anchors.fill: parent
        button1.onClicked: block.text = "test"
        button2.onClicked: messageDialog.show(qsTr("Button 2 pressed"))
    }
    
    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")
    
        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
    

    }

    MainForum.ui.qml:
    import QtQuick 2.5
    import QtQuick.Controls 1.4
    import QtQuick.Layouts 1.2

    Item {
    width: 640
    height: 480

    property alias button1: previous
    property alias button2: next
    property alias block: block
    
    RowLayout {
        anchors.verticalCenterOffset: 214
        anchors.horizontalCenterOffset: 1
        anchors.centerIn: parent
    
        Button {
            id: previous
            text: qsTr("Previous")
        }
    
        Button {
            id: next
            text: qsTr("Next")
        }
    }
    
    TextArea {
        id: block
        x: 72
        y: 8
        width: 498
        height: 421
        visible: true
        frameVisible: true
        tabChangesFocus: false
        readOnly: true
    }
    

    }

    Thanks,
    Ryan



  • First you should register your C++ class or object to the Quick engine, as follow :

    • register your class from your main.cpp:
    qmlRegisterType<QMyObject>("QMyObject", 1, 0, "QMyObject");
    
    • pass your object as a property of the engine context, from your main.cpp :
    QMyObject myObject;
    engine.rootContext()->setContextProperty("myObject", &myObject);
    

    From now on, your C++ will be available from your QML...

    • If you registered your class, you will be able to add qml Element of your class from you main.qml :
    import QMyObject 1.0
    QMyObject{
    }
    
    • if you passed your object as a property, from your QML you simply will have your "myObject" available as QML element...

    Then you have several option to achieve your purpose, you can either :

    • connect your button signal to your QMyObject slot
    • define a string property into you QMyObject that will contains what you want to show - and defines your TextArea.text to use it


  • Thanks for the response!

    I'm having some trouble getting qmlRegisterType to work.

    here's my main.cpp:
    #include <QApplication>
    #include <QQmlApplicationEngine>

    #include <test.h>

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

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
    qmlRegisterType<Test>("Test", 1, 0, "Test");
    
    return app.exec();
    

    }

    I'm getting compile the following compile time errors:

    ../test/main.cpp:13:5: error: use of undeclared identifier 'qmlRegisterType'
    qmlRegisterType<Test>("Test", 1, 0, "Test");

    Do I need to include something to get access to qmlRegisterType?



  • including QtQml fixed the issue with qmlRegisterType

    Still working on getting the other stuff working



  • Is there a way to connect c++ to qml? Like a class signal to the qml slot?

    Thanks,
    Ryan


  • Moderators

    @clarity
    Read this to publish a C++ QObject to QML.
    Then you can bind it's properties to any QML property.
    Important is that the QObject uses the Q_PROPERTY macro specifying a change-signal (using NOTIFY in the property macro).
    And of course make sure you call this signal whenever the value of the property changes (best in the setter method of the property)



  • @clarity if you need to react on QML from a signal emitted in your c++ object, you can simply use this in your QML file : (considering you have added myObject as context property - as mentioned earlier - and your objects emits a signal mySignal)

    Connections{
          target:myObject
          onMySignal: ///do whatever you need
     }
    


  • I'm getting an error when I run the code below. The error is: qrc:/main.qml:34:21: Unable to assign [undefined] to String

    Here's the code!

    test.h:
    #ifndef TEST_H
    #define TEST_H

    #include <QObject>

    class Test : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)

    public:
    explicit Test(QObject *parent = 0);
    QString text() const;
    void setText(QString txt);

    signals:
    void textChanged();

    public slots:
    void testSlot();

    protected:
    QString m_text = "Not Set";
    };

    #endif // TEST_H

    test.c:
    #include "test.h"

    #include <QDebug>

    using namespace std;

    Test::Test(QObject *parent) : QObject(parent)
    {
    }

    void Test::testSlot() {
    qDebug() << "Test::testSlot called" << endl;
    this->setText("test slot called");
    }

    QString Test::text() const {
    return this->m_text;
    }

    void Test::setText(QString txt) {
    this->m_text = txt;
    emit textChanged();
    }

    main.c:
    #include <QApplication>
    #include <QQmlApplicationEngine>

    #include <QtQml>

    #include <test.h>

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

    qmlRegisterType<Test>("Test", 1, 0, "Test");
    
    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
    Test t;
    
    engine.rootContext()->setContextProperty("Test", &t);
    
    QObject *item = engine.rootObjects().at(0);
    
    QObject::connect(item, SIGNAL(buttonPressed()),
                     &t, SLOT(testSlot()));
    
    return app.exec();
    

    }

    main.qml:
    import QtQuick 2.5
    import QtQuick.Controls 1.4
    import QtQuick.Dialogs 1.2

    import Test 1.0

    ApplicationWindow {
    id: mainWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    signal buttonPressed();
    
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }
    
    MainForm {
        anchors.fill: parent
        button1.onClicked: block.text = "prev clicked"
        button2.onClicked: mainWindow.buttonPressed()
        block.text: Test.text
    }
    
    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")
    
        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
    

    }

    Thanks!



  • I went on #qt-quick on free node, and w00t helped me.

    Here's the fixed code:

    test.h:
    #ifndef TEST_H
    #define TEST_H

    #include <QObject>

    class Test : public QObject
    {
    Q_OBJECT
    Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)

    public:
    explicit Test(QObject *parent = 0);
    QString text() const;
    void setText(QString txt);

    signals:
    void textChanged();

    public slots:
    void testSlot();

    protected:
    QString m_text = "Default String";
    };

    #endif // TEST_H

    test.cpp:
    #include "test.h"

    #include <QDebug>

    using namespace std;

    Test::Test(QObject *parent) : QObject(parent)
    {
    }

    void Test::testSlot() {
    qDebug() << "Test::testSlot called" << endl;
    this->setText("test slot called");
    }

    QString Test::text() const {
    return this->m_text;
    }

    void Test::setText(QString txt) {
    this->m_text = txt;
    emit textChanged();
    }

    main.cpp:
    #include <QApplication>
    #include <QQmlApplicationEngine>

    #include <QtQml>

    #include <test.h>

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

    QQmlApplicationEngine engine;
    
    Test t;
    
    engine.rootContext()->setContextProperty("Test", &t);
    
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    
    QObject *item = engine.rootObjects().at(0);
    
    QObject::connect(item, SIGNAL(buttonPressed()),
                     &t, SLOT(testSlot()));
    
    
    
    return app.exec();
    

    }

    main.qml:
    import QtQuick 2.5
    import QtQuick.Controls 1.4
    import QtQuick.Dialogs 1.2

    ApplicationWindow {
    id: mainWindow
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    signal buttonPressed();
    
    menuBar: MenuBar {
        Menu {
            title: qsTr("File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: console.log("Open action triggered");
            }
            MenuItem {
                text: qsTr("Exit")
                onTriggered: Qt.quit();
            }
        }
    }
    
    MainForm {
        anchors.fill: parent
        button1.onClicked: block.text = "prev clicked"
        button2.onClicked: mainWindow.buttonPressed()
        block.text: Test.text
    }
    
    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")
    
        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
    

    }

    Thanks everyone!


Log in to reply
 

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