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.2ApplicationWindow {
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.2Item {
width: 640
height: 480property 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?
-
@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.2import 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.2ApplicationWindow {
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!