I've stumbled across a problem I can't solve on an elegant way right now.
The situation: I have a callback function which is called from outside my application. The callback function has to update some gui object.. Since I can't call (for example) repaint() from within another thread, I have to finde some way to add a function call to the main event loop so the task gets executed at some time.
One possible way would be to use this:
QMetaObject::invokeMethod(object, "functionName", Qt::QueuedConnection, Q_ARG(float, value));
However, this just gives me the response that no such Method "Object::functionName". (which is obviously a lie!)
I've also read about connecting a signal to a slot which will be called from the event loop by setting the connection type to Qt::QueuedConnection. However, using QOjbect.:connect() won't work since I don't knwo which object the signal needs to get. Nice would be something like
QObject::emit(object, SIGNAL(function(flaot)), arg);
QMetaObject::invokeMethod is usually what you should use in this kind of situation. Make sure that:
object is a QObject subclass with the Q_OBJECT macro at the top
functionName is either declared in the slots section or has the Q_INVOKABLE macro
Related
I created a command-line program. I now want to add a Qt5 GUI wrapper onto it. (I am very new to Qt5 C++ programming) Previously the program simply displays command-line outputs, now I want it to display outputs on the Qt5 window. (I have converted the core code of the CLI program into a library)
My Qt5 program (a class inheriting QMainWindow) starts my library in a new STD thread. (Is using STD thread correct?) While my library is being executed (and it can take hours), it returns outputs in callback functions. In those callback functions I want to display those outputs in a QTextEdit instance; And so my Qt5 crashes all the time (and the console always says "Segmentation fault (core dumped)"), as this must be the wrong way to modify QObject.
How should I do it? What is the correct way of accessing/modifying QObject instances in a threaded function? (I want to run my library in another thread (under multithreading) because I don't want to freeze my Qt5 window) Do I need to lock a mutex? Perhaps I should use a queue structure and collect any outputs with the queue and read the queue to update my QTextEdit instance within QMainWindow (but now I need a loop function)? I hope, a kind expert can advise me.
I myself have found the solution.
One must use QThread. I think, STD thread can never access/modify QObject instances?
https://doc.qt.io/qt-5/qthread.html
the important lines:
-initialize:
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
-invoke:
workerThread->start();
The callback functions must be able to see the thread instance and call this "emit" function. This "emit" function is automatically defined in the .moc file. (Notice: the token "emit" is a macro.)
in the documentation page
emit resultReady(result);
In my case my callback functions call this function with the thread variable.
emit workerThread->resultReady(result);
So whenever this "resultReady" is called, the "handleResults" function gets called. In my case the "handleResults" function is defined inside my QMainWindow-inheriting "myMainWindow" class.
void QMainWindow::handleResults(const QString &s){
// Finally I can access/modify the QTextLine instances XDDD
}
One difficulty is, I must use a global variable to pass parameters into my library code whenever I invoke this "workerThread->start();" line.
Thanks anyway. XD
I would like to understand a simple piece of code I came across. It is a connection between an object of the interface and two signals.
The code is:
connect( ui->checkbox_legEnabled,
SIGNAL( stateChanged( int ) ), SIGNAL( edited() ) );
What is the meaning of this line of code?
Thanks,
Sara
With Qt signals and slots, you can directly connect one signal to another signal (or non-signal member function), without having a slot in between. See connection function invoked here is this overload of QObject::connect.
This line of code hence means, whenever the object ui->checkbox_legEnabled (presumably some kind of QCheckbox) emits the stateChanged signal (that has an int parameter passed along), directly emit another signal (or ordinary member function) edited (without parameters).
Short answer is you can connect a signal to another signal and that means that the second signal will also emit whenever the first signal is emitted, read more about signals and slots in the documentation here, also check out the new way to call connect (with function pointers)
Now in your case what it does it's basically allows you to keep the ui private, but in the same time forward the signals you want to the outside of your object, by allowing other objects to connect to the signal(s) you provide in the interface.
Incomplete usage example (based on your code, i named the class that contains your code MyWidget): the main-window (or whoever) that has access to your widget can be notified whenever something changes inside, by connecting to the edited signal:
void MainWindow::createMyWidget()
{
m_myWidget = new MyWidget(this);
connect(m_myWidget, &MyWidget::edited, this, &MainWindow::myWidgetWasEdited));
}
This way whenever something changes inside MyWidget the MainWindow can be notified about the edit and it can take the necessary actions inside the myWidgetWasEdited slot.
This can be expanded, if needed, to provide an signal for each particular "edit" instead of a single generic edited signal (but this depends on your needs).
I am new to Qt. I have worker thread that is an std::thread. The worker thread function continuously fetches some some data in a loop. The size of the data is frequently updated on a Text element on a QML UI. I have a listener callback which is nothing but an std::function and it gets called from the thread's function. It sends me callbacks based on which I updated the Text element on QML. I update it using signal slot mechanism.
Following is the QML : Text element:
Text {
id: mytext
objectName: "mytextobject"
function slotUpdateData(someValue){
mytext = someValue
}
}
SignalUpdateData is connected with slotUpdateData which resides on QML side. Every time I get the data event callback from the std::thread, I emit SignalUpdateData which updates the QML Text element on UI.
void CallBackReceivedFromWorkerThread(float someValue) {
emit SignalUpdateData(someValue)
}
Following is how I have connected this C++ signal with the QML slot
QObject::connect(this, SIGNAL(SignalUpdateData(QVariant)), myTextItemQObject, SLOT(slotUpdateData(QVariant)));
And all of this works fine. No crashes, lock-ups, nothing.
As per my understanding, since the worker thread's function is triggering the callback, the execution control is on the worker thread when the callback is received. So when doing emit SignalUpdateData(someValue), we'er still on the worker thread. And as far as I know from my previous experience in android & java, we cannot update the UI from anywhere outside the main thread of the application.
So, How is this working ? Is emit SignalUpdateData(someValue) putting the call into the main UI thread's event loop ? Is Qt still making the UI change on main thread in spite of me calling for it from a worker thread ? If my approach is fine, then does it have performance implications ? What is the best recommendation to do this ?
I want to be very sure about this & not just lucky about making this to work. Should I use a Qt::Connection_enum as well for best approach ?
You're leveraging Qt the way it was meant to be! And you've run into it accidentally: that's a sign of a decent design - it "just works". Hooray for you, hooray for Qt :)
It's working because Qt has been designed specifically to make it work, and you're using the default automatic connection whose raison d'être is to help you out in this specific case. So you happen to be doing everything right: change nothing!
When you emit a signal, Qt acquires relevant source and destination object mutexes, and compares the receiving object's thread() to QThread::currentThread(). If they are identical, the slot/functor is called immediately: it happens in the body of the signal, so the slot is called before the signal returns. This is safe as the target object is used from its thread(), where it's safe.
If target->thread() != QThread::currentThread(), then a QMetaCallEvent is queued to the target object. The event contains the (equivalent of) slot method pointer and a copy of any parameters passed by the slot. The QObject::event implementation handles the event and executes the call. The target object thread's event loop is on the call stack, since its job is to deliver the queued events to the object.
The above is, in a nutshell the meaning of a Qt::AutoConnection. If you're using Qt::QueuedConnection, the 2nd case applies no matter what the threads are. If you're using Qt::DirectConnection, the 1st case applies no matter what.
My guess is that >95% of the uses of a non-automatic connection type in Qt-related questions on SO are unnecessary and stem from lack of understanding and resorting to what amounts to magic incantations.
Does Qt offer functionality to know the number of queued signals that are pending for a given slot to process? Is there a way to clear them? For example, if several emits are done on a signal connected to a given slot, how could someone know the amount of these emitted signals?
QMetaObject::Connection class has a laconic interface and does not seem to offer related functionality. Deleting the object that receives the signals, hence destroying the connections, solves the problem. But is there a way to do this without disconnecting the slots or deleting the receiving objects?
The reason you ask the question most likely indicates that your design is broken. The signals and slots are a mechanism to decouple code. The objects connected together should behave themselves no matter how many senders or receiver are there, and certainly shouldn't attempt to track such matters!
It'd be wiser to fix the issue at the source by altering the design. If you are uffering from an event storm e.g. due to changing a widget's data in a slot, the slot should be very lightweight and only schedule an update of the widget by calling update(), but never forcing an immediate repaint. This leverages repaint event compression done by Qt. You might wish to compress your own events too.
Connection types in Qt
Signals and slots in Qt can be delivered using a direct, queued or blocking connection. The automatic type is not really a fixed connection type. It is an instruction to resolve the type for every receiver, at every signal emission into either a direct or queued type.
The direct connection is like any indirect function call: nothing is queued, and the slot is called from within the body of the signal method:
// all direct-connected slots/functors are invoked before mySignal() returns
emit mySignal();
The queued connection posts a QMetaCallEvent to the receiving object thread's event loop. That event contains the arguments of the call, or carries the functor. Is is handled by QObject::event(). You can certainly intercept such events. For details, see this question.
As far as I know, it is not possible to access the queue.
First of all, if the slot is in a QWidget subclass, in the GUI thread, then you can just update the member variables and call update(), and then just use the current values in paintEvent() when it gets called. These are automatically compressed, so there will be just one repaint event, no matter how many times update() gets called.
However, if the slot is not related to painting, or not in the GUI thread at all, then you need something else.
A simple solution to many cases needing this is to use a 2nd slot and a single-shot QTimer with delay 0 (or even longer delay if desirable).
Here's some example code, which should give you the idea of what I mean:
// in constructor, set mActualSlotTimer to
// singleshot, interval 0, parent this (needed for multi-threaded use)
// and connect timeout() to privateActualSlot()
// public slot for receiving the signal from outside
void MyClass::actualSlot(int data) {
// class member to store the new data value until it can be set
mNewData = data;
// restart the timer, no matter if it was already running or not
mActualSlotTimer.start();
}
// "private" slot for actually doing the change
void MyClass::privateActualSlot() {
// maybe useful: if (this->mData == this->mNewData) return;
mData = mNewData;
// do whatever else needs to be done!
}
Obviously, if your public slot does not actually take any parameters, then you don't need mData and mNewData.
One thing to note about this approach is, it works on all connections, it's not limited to just Qt::QueuedConnecton. As a consequence, it also makes using Qt::BlockingQueuedConnection kinda pointless.
A disclaimery note: I briefly checked Qt source code and it seems using timer with interval 0 should be ok: restarting the timer will work as expected. But if there still seems to be too many calls to privateActualSlot, then providing a suitable interval might be necessary. I have usually wanted a little delay (5 ms for example) to throttle things down a bit more than "as often as possible", so have not tested this extensively with interval 0.
I know that normally you wouldn’t do what I’m asking. I understand that these two layers should be separate and connect via signal/slot mechanism, which maybe asynchronous if we deal with threads.
Understanding this, I still need to call qml signal handler synchronously from SG thread. Qml objects live in GUI thread, thus emitting a signal from SG thread (particularly from updatePaintNode() method) results in asynchronous event.
I have read docs and I have no problem calling qml function synchronously from cpp from another thread. For example:
QMetaObject::invokeMethod(this, "myNiceQmlFunction", Qt::DirectConnection);
But imagine this:
//some.cpp
signal void callQmlHandler();
//some.qml
MyObject {
onCallQmlHandler: {
// do something right now
}
}
I don’t know how to call onCallQmlHandler synchronously via QMetaObject::invokeMethod.
I don’t create qml object from code and at this point in cpp I don’t have access to qml component to look for its children, find MyObject there by name and call its handler (if it is possible). Anyways, this is not a beautiful way to do so.
I tried to find signal handler among QMetaObject methods, but it's not there. Nor it is in properties list (I checked just in case, because syntax of signal handlers is similar to property's one)
Does anyone know if I miss the right syntax to call signal handler via QMetaObject::invokeMethod or it is not possible at all? Any ideas?
You can pass a C++ object to QML using its context.
qmlviewer.rootContext()->setContextProperty("backend", backend);
QML side:
Connections {
target: backend
onCallQmlHandler: {
// do something right now
}
}
When you emit callQmlHandler from backend object, you get the handler executed.
But Connections object may create queued connections, so you can implement your own DirectConnections. At the end of this post you have an implementation.
However QML is excecuted by a QML engine, which I think is intended to be run by a single thread, so you may run into a bigger problem unless you really know what you are doing!