Solved Signal of QML and slot of C++ in Qt Controls2
-
Hello,
I am new to Qt Controls2. I am designing a classes in which text field-text should be displayed on the screen.I want to execute this process by Signal of qml and handle it in cpp slot. Tried many examples just could not find a matching one to my problem.
So please give me a solution, couse I am stuck in it for more than 2 days.
What the aim is->
I want to print the content of the textfield by using my cpp file.
with Button click I am emitting the signal with textfield input and It should call the cppSlot of my cpp file and there it should print that textfield input. either in the console or It could be anywhere as you guys can suggest.Qml file is working, couse I tried running the onclick property with direct console.log() and as well as created a function to print that text in the textfield.
here is my QML file->
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")Page { id:root signal qmlSignal(var msg) Pane { id: pane Layout.fillWidth: true RowLayout { width: parent.width TextArea { id: messageField text:qsTr("Akshay") Layout.fillWidth: true placeholderText: qsTr("Compose message") wrapMode: TextArea.Wrap } Button { id: sendButton text: qsTr("Send") enabled: messageField.length > 0 onClicked: root.qmlSignal(messageField.text) } } }}}
and Here is my CPP file->
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include<QObject>
#include <QtQuickControls2/QtQuickControls2>class MyClass:public QObject
{
Q_OBJECT
public slots:
void cppSlot(const QVariant &msg)
{
qDebug() << "Called the C++ slot with message:" << msg;
}
};int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml")));
// QObject *item=engine.rootObjects().value(0);
// MyClass Class;
// QObject::connect(item,SIGNAL(qmlSignal(QVariant)),Class,SLOT(cppSlot(QVariant)));
return app.exec();
}
the commented section is the code I am trying and its giving me an error,
-
@Akshay-Singh said in Signal of qml and slot of cpp in Qt control 2(not working)......Please Help:
MyClass Class; QObject::connect(item,SIGNAL(qmlSignal(QVariant)),Class,SLOT(cppSlot(QVariant)));
You need to pass pointers to QObject::connect(). Pass
&Class
, notClass
. -
So guys Now the problem solved with some minute changes I used this site->
https://andrew-jones.com/blog/qml2-to-c-and-back-again-with-signals-and-slots/as my reference...and thanks @JKSH ...that was one of the main problem.
-
Hi Akshay,
You tried a way. But check below steps(which normally we do when we want to connect QML and CPP via signal slot):
and Here is my CPP file->
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QDebug>
#include<QObject>
#include <QtQuickControls2/QtQuickControls2>class MyClass:public QObject
{
Q_OBJECT
public slots:
void cppSlot(QString msg) /// You cannot use QString& since reference variable cannot be recognized from QML -> C++ code
{
qDebug() << "Called the C++ slot with message:" << msg;
}
};int main(int argc, char *argv[])
{
....QQmlApplicationEngine engine; QQmlContext* context = engine.rootContext(); MyClass class; context->setContextProperty("myClassInstance", &class); /// Register your class object to QML meta system. engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec();
}
/// in QML
...
Button {
id: sendButton
text: qsTr("Send")
enabled: messageField.length > 0
onClicked: myClassInstance.cppSlot(messageField.text); /// call slot directly. You can also make Q_INVOKABLE function to be called from here.
} -
Ohkay....I Implemented this... and It worked too. as well read about the
setContextPropertyfor the one who are new as me, correct me if I am wrong
here what we are doing is->context->setContextProperty("myClassInstance", &class);
we are giving a alias name to the instance object of the class or say we are passing the address of the object to the qml file.
when qml file will get this "myClassInstance" it will use it as an instance object to call the Slot named as cppSlot() of MyClass.
Then
onClicked: myClassInstance.cppSlot(textfield.text)
will call the cppSlot() function and it will do it's work there.
Thanks @RajeeshRaveendran
please clear my one more doubt,We can do the same procedure by three ways
1)->Normal Signal and Slot Handling
2)->using setContextProperty()
3->Q_INVOKABLE functionwhich method is more used in day to days projects??
In other words....Which method should I be more focused on while integrating QML and C++?? -
If you want to use in QML side in any way an object created in C++, you use setContextProperty to make the object available for QML engine.
You can receive signals sent by a C++ object in QML as long as the object is available.
You can use C++ slots as normal functions in QML as long as the object is available.
You can use Q_INVOKABLE C++ functions as normal functions in QML as long as the object is available.
"Which method should I be more focused on?" It depends on your needs. If you need a function to be a slot in C++ (you connect it with C++ signals) then it should of course be a slot. If not, Q_INVOKABLE is enough, but you don't loose anything if you make it a slot. Signal is signal, you can't receive signals from C++ objects if you don't make them to be signals, can you? As long as I know you can't connect a C++ slot with a QML signal, so calling a C++ function from QML is the only option.
One other thing you should be familiar with is C++ properties, http://doc.qt.io/qt-5/properties.html. Set the NOTIFY signal for a property and you can use it automatically in QML bindings.
-
Contrary to what I just said, you can connect a QML signal to a C++ slot, as the mentioned blog post demonstrates. It's just not very convenient when you have a complicated QML object tree and using the objects from the QML tree isn't a recommended way to handle things (although it's of course up to you if you want to use it and if it fits your needs).
Here is an example demonstrating Q_INVOKABLE and C++ property which are used in QML.
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "x.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); X x; QQmlApplicationEngine engine; QQmlContext* context = engine.rootContext(); context->setContextProperty("objectX", &x); engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }
x.h:
#ifndef X_H #define X_H #include <QObject> class X: public QObject { Q_OBJECT Q_PROPERTY(QString text MEMBER m_text NOTIFY textChanged) QString m_text; public: explicit X(); Q_INVOKABLE void setText(QString text); signals: void textChanged(QString& text); }; #endif // X_H
x.cpp:
#include "x.h" X::X():QObject(),m_text("initial text") {} void X::setText(QString text) { m_text = text; emit textChanged(m_text); }
main.qml:
import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") RowLayout { Label { text: objectX.text } Button { text: "Click to change C++ object text" onClicked: { objectX.setText("new text") } } } }
-
If you want to decouple the button and objectX in my example you can use Connections. It's a bit like C++ connect().
RowLayout { Label { text: objectX.text } Button { id: b1 text: "Click to change C++ object text" //onClicked: { // objectX.setText("new text") //} } } Connections { target: b1 onClicked: { objectX.setText("new text") } }
If you make it
Connections{target: b1; onClicked: {objectX.setText("new text")}}
you see better how similar and dissimilar it's to connect().
-
@Eeli-K Thank you so much...this was my next problem....that you just solved....
I was going to google it down about the PROPERTY. and this is the best example I can get .First I used CHAT TUTORIAL of QUICK CONTROL 2 but in the end it became very complex.
So used this post.So with the earlier post of your Its clarified that....
Q_INVOKABLE and PROPERTY gives the code an edge in making it more user readable and understandable.And mainly these both are used to make the code loosely coupled. If changes to be made in some context then only some parts of the code is only need to be changed.
Hence these are more used in Big Projects andSignals and slots are mainly used when passing the signals to the selected slot from multiple selections.
and vice versa.In other words-> when there is possibility in your code that functionality might change from objects to objects and objects to mechanism (if there are presence of multiple slots and signals of same type and parameter) then with using
QOBJECT::CONNECT(.....);
we can change these functionality by changing the connection between the slots and signals.hence they are used in today's projects just to connect the functionality between objects and real parts are handled by Q_INVOKABLE and PROPERTY type functions.
correct me If I am wrong.
AND thanks again..
-
@Akshay-Singh
"PROPERTY gives the code an edge in making it more user readable and understandable"Yes, but not so much with Q_INVOKABLE. The only thing Q_INVOKABLE does is it makes us able to call the function via the Qt meta object system, in this case to use it normally, as a normal function, from QML. From the QML viewpoint Q_INVOKABLE doesn't help in decoupling any more than any function.
Qt's Signal-slot system has been created to enable event-based system with very loose coupling. It's also very readable and understandable once you get accustomed to it.
"hence they are used in today's projects just to connect the functionality between objects and real parts are handled by Q_INVOKABLE and PROPERTY type functions."
What do you mean by "real parts are handled by..."? Q_INVOKABLE methods are just methods. PROPERTY creates very handy shortcuts for some functionality which otherwise should be written explicitly, and it makes data available via the meta object system. And I repeat that you can make member functions slots instead of Q_INVOKABLES if you want to use them in QML. Q_INVOKABLE doesn't give you any edge over slot, it just gives explicit hint that the function is not used as a slot in C++.
To add multiple QML signal-slot connections to your arsenal (instead of just one onSignal handler) see Connecting Signals to Methods and Signals in http://doc.qt.io/qt-5/qtqml-syntax-signals.html. You can connect a QML signal also to a C++ slot or to a Q_INVOKABLE.
-
@Eeli-K Sorry for the late reply, due to Holi Festival I was unable to open the forum.
Well thanks so much for clearing all the doubts. Understood the uses of every aspects and will imply these tutorials,as per the project will be of in need.Thank you so much all of you guys, for giving your time to this post.....Helped me a lot as a beginner.