PDA

View Full Version : Qt Signal&Slots



Gumis
1st December 2016, 23:19
Hello everyone,

I have encountered on problem of signal&slots. When I used QObject::connect function in main, where QGuiApplication is declared, everything works properly. However, when I put the code responsible for finding object from QML and handling the connection on outside class, the funcionality doesn't work. Please for help ;)

Not working code:


#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
#include <QObject>
#include <QQmlProperty>
#include "fun.h"


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


fun f;
f.start();


return app.exec();
}

Source of the class

#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
#include <QObject>
#include <QQmlProperty>
#include "fun.h"


fun::fun()
{

}

void fun::start()
{

QQmlApplicationEngine engine;

QQmlComponent componentMainWindow(&engine, QUrl(QStringLiteral("qrc:/main.qml")));

qDebug() << componentMainWindow.errors();

QObject *objectMainWindow = componentMainWindow.create();

QObject *objectKwad = objectMainWindow->findChild<QObject*>("kwadlo");

objectKwad = objectKwad->findChild<QObject*>("kwad");

if (objectKwad) {
qDebug() << "Object was found";

} else {
qDebug() << "Object with given name was not found";
}

objectKwad->setProperty("width", 120);
connect(objectKwad, SIGNAL(buttonClick()), this, SLOT(cppSlot()));

}

Header of the class

#ifndef FUN_H
#define FUN_H

#include <QObject>
#include <QDebug>


class fun : public QObject
{
Q_OBJECT
public:
fun();
void start();

public slots:
inline void cppSlot()
{
qDebug() << "Button was clicked";
}
};

#endif // FUN_H


Working code, when I use the QObject::connect in main.

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>
#include <QObject>
#include <QQmlProperty>
#include "fun.h"


int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
/*fun f;
f.start();*/


QQmlApplicationEngine engine;

QQmlComponent componentMainWindow(&engine, QUrl(QStringLiteral("qrc:/main.qml")));

qDebug() << componentMainWindow.errors();

QObject *objectMainWindow = componentMainWindow.create();

QObject *objectKwad = objectMainWindow->findChild<QObject*>("kwadlo");


objectKwad = objectKwad->findChild<QObject*>("kwad");
if (objectKwad) {

} else {
qDebug() << "Object with given name was not found";
}
objectKwad->setProperty("width", 120);
QObject::connect(objectKwad, SIGNAL(buttonClick()), &f, SLOT(cppSlot()));

return app.exec();
}

d_stranz
2nd December 2016, 00:57
The QQmlApplicationEngine and QQmlComponent you create in lines 18 and 20 of fun.cpp go out of scope as soon as the start() function exits, so all of the QQmlComponent's children and their connections will be destroyed when it is. In your working code, that QQmlApplicationEngine and QQmlComponent do not go out of scope until the program exits, so all references to them and their children are valid for the entire program.

You can change your fun class so that it works by making "engine", "componentMainWindow", and "objectMainWindow" member variables of the fun class, and initializing them in the constructor for fun:



#ifndef FUN_H
#define FUN_H

#include <QObject>
#include <QQmlApplicationEngine>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QDebug>


class fun : public QObject
{
Q_OBJECT
public:
fun();
void start();

public slots:
inline void cppSlot()
{
qDebug() << "Button was clicked";
}

private:
QQmlApplicationEngine engine;
QQmlComponent componentMainWindow;
QObject * objectMainWindow;
};

#endif // FUN_H




#include <QDebug>
#include <QObject>
#include <QQmlProperty>
#include "fun.h"


fun::fun()
: componentMainWindow( &engine, QUrl(QStringLiteral("qrc:/main.qml") )
{
objectMainWindow = componentMainWindow.create();
}

void fun::start()
{
qDebug() << componentMainWindow.errors();


QObject *objectKwad = objectMainWindow->findChild<QObject*>("kwadlo");

objectKwad = objectKwad->findChild<QObject*>("kwad");

if (objectKwad) {
qDebug() << "Object was found";

} else {
qDebug() << "Object with given name was not found";
}

objectKwad->setProperty("width", 120);
connect(objectKwad, SIGNAL(buttonClick()), this, SLOT(cppSlot()));

}

anda_skoa
2nd December 2016, 08:02
However, when I put the code responsible for finding object from QML and handling the connection on outside class

Which is a bad idea anyway.

But d_stranz has the answer if you really want to go down that path.

Cheers,
_