How to catch the signal emitted from C++ global function in QML
-
@raven-worx i tried as said by @sierdzio but i am not able to catch the signal.
here is the code.
.cpp#include "globaltest.h" Globaltest testobj; Globaltest::Globaltest(QObject *parent) : QObject(parent) { } void Globaltest::test() { qDebug()<<"test called"<<endl; output(); } void output() { qDebug()<<"output function called"<<endl; testobj.testSignal(); }
main.cpp
#include <QGuiApplication> #include <QApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "globaltest.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Globaltest testobj; qmlRegisterType<Globaltest>("com.globalCpp",1,0,"Globaltest"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("TestObject",&testobj); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.7 import QtQuick.Window 2.2 import com.globalCpp 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Connections { target: TestObject onTestSignal: console.log("Signal caught") } MouseArea{ id: mouse anchors.fill: parent onClicked: { TestObject.test() } } }
-
@raven-worx i tried as said by @sierdzio but i am not able to catch the signal.
here is the code.
.cpp#include "globaltest.h" Globaltest testobj; Globaltest::Globaltest(QObject *parent) : QObject(parent) { } void Globaltest::test() { qDebug()<<"test called"<<endl; output(); } void output() { qDebug()<<"output function called"<<endl; testobj.testSignal(); }
main.cpp
#include <QGuiApplication> #include <QApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "globaltest.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Globaltest testobj; qmlRegisterType<Globaltest>("com.globalCpp",1,0,"Globaltest"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("TestObject",&testobj); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.7 import QtQuick.Window 2.2 import com.globalCpp 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Connections { target: TestObject onTestSignal: console.log("Signal caught") } MouseArea{ id: mouse anchors.fill: parent onClicked: { TestObject.test() } } }
@Naveen_D
you are creating two different instances of your your object. One in the main() and one in the cpp file.
You need to ensure that you operate on the same instance. Take a look at the Singleton pattern:class Globaltest { public: static Globaltest* Globaltest::Instance() { //static method static Globaltest* instance = new Globaltest; return instance; } private: Globaltest(); //hidden constructor --> only allow to use our static Instance() method };
-
@Naveen_D
you are creating two different instances of your your object. One in the main() and one in the cpp file.
You need to ensure that you operate on the same instance. Take a look at the Singleton pattern:class Globaltest { public: static Globaltest* Globaltest::Instance() { //static method static Globaltest* instance = new Globaltest; return instance; } private: Globaltest(); //hidden constructor --> only allow to use our static Instance() method };
@raven-worx without using singleton...it is not possible? becoz i have a global object of that class...
-
@raven-worx without using singleton...it is not possible? becoz i have a global object of that class...
@Naveen_D
sure, but you need to make sure you are using the right object instance. The singleton is an easy and understandable mechanism, which prevents some possible poitfalls.
As i said in your posted example you are using 2 different instances. Define the global object as global static object in the header file instead of the source file. -
@Naveen_D
sure, but you need to make sure you are using the right object instance. The singleton is an easy and understandable mechanism, which prevents some possible poitfalls.
As i said in your posted example you are using 2 different instances. Define the global object as global static object in the header file instead of the source file.@raven-worx
if i define the global object as global static object in the header file instead of the source file. it is not necessary to again create an object in main.cpp and use context property?..without this i can directly catch the signal using signal handler in qml ? -
@raven-worx
if i define the global object as global static object in the header file instead of the source file. it is not necessary to again create an object in main.cpp and use context property?..without this i can directly catch the signal using signal handler in qml ?@Naveen_D said in How to catch the signal emitted from C++ global function in QML:
it is not necessary to again create an object in main.cpp and use context property?
the context property of course is still necessary. But not the duplicate object creation. Instead reference the static global one from the header file wherever you need it.
-
@Naveen_D said in How to catch the signal emitted from C++ global function in QML:
it is not necessary to again create an object in main.cpp and use context property?
the context property of course is still necessary. But not the duplicate object creation. Instead reference the static global one from the header file wherever you need it.
@raven-worx i want to use this global obj in global function to emit the signal from that function.
the way i am declaring the global function is right ?#ifndef GLOBALTEST_H #define GLOBALTEST_H #include <QObject> #include <QDebug> void output(); class Globaltest : public QObject { Q_OBJECT static Globaltest *s_instance; public: explicit Globaltest(QObject *parent = 0); signals: void testSignal(); public slots: Q_INVOKABLE void test(); }; #endif // GLOBALTEST_H
-
@Naveen_D said in How to catch the signal emitted from C++ global function in QML:
it is not necessary to again create an object in main.cpp and use context property?
the context property of course is still necessary. But not the duplicate object creation. Instead reference the static global one from the header file wherever you need it.
Hi, as you said i have only one instance of the object in the below code but when i use this object in set context property i am getting QVariant error...the error is
/home/ubuntu/Qt5.7.0/5.7/gcc_64/include/QtCore/qvariant.h:471: error: 'QVariant::QVariant(void)' is private
inline QVariant(void ) Q_DECL_EQ_DELETE;and if i remove the '&' and run the code i get this qml error
QML debugging is enabled. Only use this in a safe environment.
qrc:/main.qml:20: TypeError: Cannot call method 'test' of nullcan anyone tell what is wrong in the code and what i need to change
Thanks.h
#ifndef GLOBALTEST_H #define GLOBALTEST_H #include <QObject> #include <QDebug> void output(); class Globaltest : public QObject { Q_OBJECT public: explicit Globaltest(QObject *parent = 0); signals: void testSignal(); public slots: Q_INVOKABLE void test(); }; extern Globaltest *MySender; #endif // GLOBALTEST_H
.cpp
#include "globaltest.h" Globaltest *MySender; Globaltest::Globaltest(QObject *parent) : QObject(parent) { } //Globaltest *Globaltest::s_instance = 0; void Globaltest::test() { qDebug()<<"test called"<<endl; output(); } void output() { qDebug()<<"output function called"<<endl; MySender= new Globaltest; MySender->testSignal(); }
main.cpp
#include <QGuiApplication> #include <QApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "globaltest.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); qmlRegisterType<Globaltest>("com.globalCpp",1,0,"Globaltest"); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("TestObject",&MySender); //Getting error here // engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); }
main.qml
import QtQuick 2.7 import QtQuick.Window 2.2 import com.globalCpp 1.0 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") Connections { target: TestObject onTestSignal: console.log("Signal caught") } MouseArea{ id: mouse anchors.fill: parent onClicked: { TestObject.test() } } }
-
You are declaring MySender to be a pointer, so using '&' in setContextProperty() is wrong. '&' is a way to extract a pointer from non-pointer variable. Here you already have a pointer, so no need for '&'.
You declare MySender variable, but you never set it to any value (meaning: you never create an object of type Globaltest). So QML engine - rightfully - complains that the object is null (== not set).
You need to set the value of MySender somewhere in your code (before call to setContextProperty), in other words:
MySender = new GlobalTest;
-
You are declaring MySender to be a pointer, so using '&' in setContextProperty() is wrong. '&' is a way to extract a pointer from non-pointer variable. Here you already have a pointer, so no need for '&'.
You declare MySender variable, but you never set it to any value (meaning: you never create an object of type Globaltest). So QML engine - rightfully - complains that the object is null (== not set).
You need to set the value of MySender somewhere in your code (before call to setContextProperty), in other words:
MySender = new GlobalTest;
-
You are declaring MySender to be a pointer, so using '&' in setContextProperty() is wrong. '&' is a way to extract a pointer from non-pointer variable. Here you already have a pointer, so no need for '&'.
You declare MySender variable, but you never set it to any value (meaning: you never create an object of type Globaltest). So QML engine - rightfully - complains that the object is null (== not set).
You need to set the value of MySender somewhere in your code (before call to setContextProperty), in other words:
MySender = new GlobalTest;
-
@raven-worx said in How to catch the signal emitted from C++ global function in QML:
also remove the line MySender= new Globaltest; from your output() method.
Doh, I did not even look at that method when writing my reply. Good hint, thanks for being so attentive @raven-worx :-)
-
Cool, good to know :-) Happy coding!