Can QtQuick app create and display MessageDialog from C++ static member function?
-
I want my C++ static member function to simply display an informational message in a dialog. Does QtQuick provide a convenience function to do this? I see how to do this with a C++ signal connected to QML slot, but in my case the C++ is a static member so cannot emit a signal.
Thanks!
-
I want my C++ static member function to simply display an informational message in a dialog. Does QtQuick provide a convenience function to do this? I see how to do this with a C++ signal connected to QML slot, but in my case the C++ is a static member so cannot emit a signal.
Thanks!
-
@Tom-asso add a static QObject member to emit the signal. Or add a function in your root QML window and invoke it from c++
@GrecKo - thanks!
I might be over-thinking this, but it's still not clear to me how this would work. I.e. I want my static C++ member function to raise an informational message dialog (with just on 'OK' button). Seems like a common use case? Are there examples that you can point to? In particular, what would the QObject::connect() call look like, if the signal is being emitted by a static member object, assuming my QML ApplicationWindow defines function showInfoDialog()?class Emitter : public QObject { signal: sendMsg(QString msg); }; class Backend { static Emitter emitter; }
Now how to connect the signal emitted by static member emitter with QML? What are the first two arguments to connect()?
main.cpp:
Backend backend; QObject::connect(&backend.emitter, SIGNAL(sendMsg(QString msg)), rootObject, SLOT(showInfoDialog(QString msg)));
The above compiles, but connect() fails at runtime:
QObject::connect: No such signal Emitter::showMessage(QString &msg)
This seems odd because the runtime "knows" that showMessage(QString &msg) is associated with the Emitter class, yet somehow doesn't recognize it as a signal. What am I doing wrong???
Thanks!
-
@GrecKo - thanks!
I might be over-thinking this, but it's still not clear to me how this would work. I.e. I want my static C++ member function to raise an informational message dialog (with just on 'OK' button). Seems like a common use case? Are there examples that you can point to? In particular, what would the QObject::connect() call look like, if the signal is being emitted by a static member object, assuming my QML ApplicationWindow defines function showInfoDialog()?class Emitter : public QObject { signal: sendMsg(QString msg); }; class Backend { static Emitter emitter; }
Now how to connect the signal emitted by static member emitter with QML? What are the first two arguments to connect()?
main.cpp:
Backend backend; QObject::connect(&backend.emitter, SIGNAL(sendMsg(QString msg)), rootObject, SLOT(showInfoDialog(QString msg)));
The above compiles, but connect() fails at runtime:
QObject::connect: No such signal Emitter::showMessage(QString &msg)
This seems odd because the runtime "knows" that showMessage(QString &msg) is associated with the Emitter class, yet somehow doesn't recognize it as a signal. What am I doing wrong???
Thanks!
@Tom-asso I think the issue you are having is that
Backend
does not expose a signal to allow you to connect, right?You could add a static function to your
Backend
class which would make the connection. That would then have access to theemitter
. To keep it clean, you could pass astd::function
as the target, which you initialise with a lambda.class Backend { public: static void connectInfoMsg(std::function<void(QString)> onInfoMsg) { QObject::connect(&emitter, &Emitter::sendMsg, onInfoMsg); } ... };
In your main.cpp:
Backend::connectInfoMsg( [&](QString msg){ rootObject->showInfoDialog(msg); }
Despite what you say, I am not sure how common this actually is as a use case. I don't recall ever having done anything like this. I would be more likely to expose an object to QML using a context property (old-fashioned way) or
qmlRegisterSingletonInstance
(modern way) that would emit signals when messages are available. Then hook up connections to dialogs on the QML side.I think you are possibly making things awkward for yourself with a design that relies on a static function.
-
@Tom-asso I think the issue you are having is that
Backend
does not expose a signal to allow you to connect, right?You could add a static function to your
Backend
class which would make the connection. That would then have access to theemitter
. To keep it clean, you could pass astd::function
as the target, which you initialise with a lambda.class Backend { public: static void connectInfoMsg(std::function<void(QString)> onInfoMsg) { QObject::connect(&emitter, &Emitter::sendMsg, onInfoMsg); } ... };
In your main.cpp:
Backend::connectInfoMsg( [&](QString msg){ rootObject->showInfoDialog(msg); }
Despite what you say, I am not sure how common this actually is as a use case. I don't recall ever having done anything like this. I would be more likely to expose an object to QML using a context property (old-fashioned way) or
qmlRegisterSingletonInstance
(modern way) that would emit signals when messages are available. Then hook up connections to dialogs on the QML side.I think you are possibly making things awkward for yourself with a design that relies on a static function.
@Bob64 - Thanks, Bob.
Emitter actually emits a signal sendMsg(). The reason that connect() failed is because I need to specify data passed as QVariant (not QMessage) when data is exchanged between C++ and QML. So the following compiles and connects properly:Emitter.h:
class Emitter : public QObject { signal: sendMsg(QVariant msg); };
main.cpp:
QObject::connect(&backend.emitter, SIGNAL(sendMsg(QVariant)), rootObject, SLOT(showInfoDialog(QVariant)));
My application includes a lot of legacy 'C' code, and passes Backend static function pointers to that C code. Now that I have it working it seems ok.
Thanks! -
T Tom asso has marked this topic as solved on