qt - setText outside of paint events not ok? - c++

Under Qt 4.7.1, Qt Creator 2.1.0, OS X 10.6.8:
I have a QLabel in the mainwindow ui, which uses Courier New / 13, with room for four lines of text.
I create four lines of text, considerably shorter than the label is horizontally, of the general format:
"my text\r\n"
I filter the text before sending it along. The only characters in the cstring will be 0x0D, 0x0A, 0x20 (space) and from there up to lower case z (0x7A') and of course the terminating zero. No other control characters - if they are received from the source, I replace them with '*'
I send the four lines of text to the QLabel as a single zero-terminated cstring via setText()
I sometimes do this at a fairly high rate, several times a second at least -- this is RDBS data from an FM station so it changes in real time:
qDebug() << rbl; // data keeps coming to console
ui->fourLineLabel->setText(rbl); // add this, display soon stops updating
This works. For a while. Then the display stops updating. This is the area at issue:
(source: fyngyrz.com)
If I leave everything else in, but take out the setText(), the problem does not occur.
I know that for some things, Qt wants painting to be done within a paint event. Is this also true of a setText() ?
Reading the docs on qt widgets, it says that widgets do their own painting within their own paint event... but the behavior here is very similar to the kind of malfappery that goes on when one actually tries to use a painter outside of a paint event. And it's definitely related to that setText(), so... mumble.
As I write this, the application has been running for hours without any display lockup, outputting the same text to the console via qDebug(). It takes about 5 minutes for the problem to occur if I uncomment the setText(). It's 100% repeatable.
Is there something I should be doing that I'm not doing, paint-wise or similar?
Thanks for any assistance.

In general you should not update Qt controls from non UI thread, only a small amount of things is allowed to do regarding a painting in non UI thread - http://doc.qt.io/qt-4.8/threads-modules.html
If you need to update UI from non UI thread - use signals and slots (QueuedConnection or BlockingQueuedConnection connections, though make sure to not create deadlock with BlockingQueuedConnection). Or if you don't want to create additional signals and slots for some easy update - use invokeMethod (it can even return value and if you use it with BlockingQueuedConnection connection type, your thread will wait until UI is updated).
And a general advice - if you have a possibility - make one call for bulk of updates to UI instead of few small calls.

It is always advised that the GUI thread interfaces with all other objects through the signal-slot mechanism. In fact, no direct calls from and to the main thread are to be made. In that manner the GUI will be responsive, and we don't end up waiting for it to come back. Certainly polling solutions are not ideal, and should be avoided as they end up using cup resources without reason.
If one is using only QThread type threads then updating the GUI should be done by using the signal-slot mechanism. When events of data presented need to be serialized using the Qt::QueuedConnection is sufficient. In your case that is true.
If not using that , then signals may not be processed in the sequence emitted. Qt::BlockingQueuedConnection should be used only when we want to restrict the caller continue from processing before the slot on the receiver has completed. This is very rarely the case for processing that happens on the GUI thread.
Special care has to be taken when we want to connect from a non-qt thread, e.g. An std thread, because the objects created e.g. in a native thread will not be known on the receiver end.
One way to update the ui from a non-ui thread is to serialize and copy your messages. Do the following (works even for non-QThreads e.g. boost::thread ):
Setup a singleton QObject that provides public methods to force-emit
signals containing the data that you want to send ,e.g. a singleton
Setup slots in objects that only accept arguments by value
Connect the signals to the slots in an object within the ui-thread
Connections must be Qt::QueuedConnection
class timer : public QObject
{
Q_OBJECT
//... write a singleton here
std::mutex mut;
public signals:
signal_tic(QString const );
public:
void force_emit_tic(QString const s )
{
std::lock_guard<std::mutex> l(mut);
emit signal_tic(s);
}
timer & ref()
{
static timer This;
return This;
}
private:
timer(){}
};
// in a main thread object setup this connection
connect(&timer::ref(),SIGNAL(signal_tic(Qstring
const)),this,SLOT(slot_accept_tic(QString const ), Qt::QueuedConnection)
// In any other thread
timer::ref()::force_emit_tic( string_when_this_happened )
Calling directly the singleton force-emit method results in the desired behaviour. (ofcourse objects must be properly copiable for this to work)
The reason for sending by value is that if you pass a const reference to temporary residing in another thread it's lifetime is not guaranteed. Furthermore, you need to take care of serializing the messages to the ui-thread before they actually arrive or you will eventually receive one of either incosistent data or a SIGSEGV. Qt::QueuedConnection guarantees that connections are serialized only within the memory space known to QThreads.

Related

How to avoid freezing the user interface in a loop (minimal example) [duplicate]

My first naive at updating my progress bar was to include the following lines in my loop which is doing the processing, making something like this:
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
//Added these lines but they don't do anything
ui->progressBar->setValue(numberProcessed++);
ui->progressBar->repaint();
}
I thought adding the repaint() would make the execution pause while it updated the GUI, but apparently it's not that simple. After looking at the questions:
QProgressBar Error
Progress bar is not showing progress
it looks like I'm going to have to put the data processing in a different thread and then connect a signal from the data processing thread to the GUI thread to update the progressbar. I'm rather inexperienced with GUIs and threads and I was wondering if anyone could just point me in the right direction, ie what Qt classes should I be looking at using for this. I'd guess I need a QThread object but I've been looking through the QProgressBar documentation but it doesn't bring up the topic of threading.
As #rjh and #Georg have pointed out, there are essentially two different options:
Force processing of events using QApplication::processEvents(), OR
Create a thread that emits signals that can be used to update the progress bar
If you're doing any non-trivial processing, I'd recommend moving the processing to a thread.
The most important thing to know about threads is that except for the main GUI thread (which you don't start nor create), you can never update the GUI directly from within a thread.
The last parameter of QObject::connect() is a Qt::ConnectionType enum that by default takes into consideration whether threads are involved.
Thus, you should be able to create a simple subclass of QThread that does the processing:
class DataProcessingThread : public QThread
{
public:
void run();
signals:
void percentageComplete(int);
};
void MyThread::run()
{
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
emit percentageCompleted(computePercentageCompleted());
}
}
And then somewhere in your GUI code:
DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
You need to call QApplication::processEvents() periodically inside your processing loop to let it handle UI events.
As Georg says, Qt is a single-threaded co-operative multitasking environment. You get full control of your process until you relinquish it voluntarily with processEvents() - until you do that, Qt can't update the UI elements, handle async HTTP requests, handle input, or pretty much anything else. It's up to you to make sure that stuff gets a timeslice while you're in a long processing loop.
You can create a sub-class of QThread that emits a signal progressChanged, which you connect to the QProgressBar.
connect() makes the connections auto connections per default. That means that the signal-slot-mechanism already takes care of the threading issues for you, so you don't need to worry about that.

Emitting a Qt::signal from worker thread makes the UI update on main thread by default?

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.

Information and control on emitted signals and slots (Qt)

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.

Is it OK to chain signals and slots several times?

I have something like the following design of classes and I'm wondering if it's OK that I use many signal slot connections to communicate between them. There is a MainWindow class which holds all the GUI, then a Wrapper class, which provides an interface to the back-end, then there is a Controller class for spawning and managing threads and finally there are Workers which do all the work.
Now let's say I'm loading a file and want to display progress using a progress bar in the MainWindow. My Worker class sends updateProgress(int progress) to Controller::handleProgress(int progress) slot which again sends progress signal to the Wrapper class, which in return sends a progress signal to the main window, which finally updates the progress bar.
Similarly when the data has been loaded it is processed in the Wrapper class and, again, communicated through signals and slots (although with one less step).
Is it a standard way of doing things in Qt or should I rethink my design?
It is a valid possibility.
Note that Qt allows you to go even further and do the following:
QObject::connect(&sender, SIGNAL(mySenderSignal(int)),
&receiver, SIGNAL(myReceiverSignal(int));
That's right, you can bind a signal to a signal. All it does can be seen as "when the sender's signal is emitted, emit the receiver's signal".
If you don't have any specific task to perform in your intermediary slots, that might save you a few lines, while showing exactly what you're doing: you're "forwarding" a signal. Otherwise, if you must absolutely do work in between, then you must keep the signals and the slots.
Note that you still have to be sure that the signals signatures match.

QThread passing data to and from

I will try to explain what my program used to do and what I am tring to change:
I had this function that ran on a button click from the the main thread in class MainWindow : public QMainWindow :
The function looks like this and is specified inside another file:
void MakeMeshStructure(MeshStructureLayers layers,
Handle_AIS_InteractiveContext theContext,
Handle_TDocStd_Document aDoc,
MyMesh &mesh,
int detail_vertex,
double insulation_thickness,
OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}
What it does is: it works on mesh and creates geometry for every vertex, face and edge of the mesh. This geometry gets displayed with theContext. This process takes very long (30 min) and blocks the gui.
What I would like to do is to have as many threads as QThread::idealThreadCount() and to free the gui when it computes and make it faster. (Is this the right thinking?)
I would like to divide my mesh into equal parts and pass this range of vertices to my function (above) to only work with one vertex range for a seperate tread.
I have a problem to figure out how to pass this data around and to make it thread safe.
I know its alot of code but here is my attempt at solving it:
http://pastebin.com/u/mzagar
The problem is getting all the data around in the right way and getting the threads to work. Where do I have to use mutexes. On every data that can get writen at the time of the thread work by the mainthread? Very confused. ty
edit:
I edited my code: http://pastebin.com/u/mzagar
I made a struct cadData to pass the data around. This is how I start threads:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
//...
emit startMake1(aCadDatas.at(0));
//...
The problem is threads dont seem to work at the same time and also the gui freezes. Process goes in like this:
GUI freezes
things in thread 1 get done
things in thread 1 get done again
things in thread 2 get done
things in thread 2 get done again
...
GUI unfreezes
Any ideas why?
edit2:
I removed the multiple runs of the same thread by moving this to the class constructor:
connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
Since you're using QThread, you can probably avoid explicit use of mutexes and such by using Qt's thread-safe slots-and-signals mechanism to do the work for you. You would basically package the data you need to send to the thread into an object, then emit a signal that has that object as an argument. The thread would receive a copy of that object in a slot (that you had previously connected to your signal) and start using the data then. To get data back from the worker thread to the main thread, you'd do the same thing again in reverse. Here's an article with some example code.
To add to Jeremy's answer: You can do the same by sending events between QObjects instead of using the signal-slot mechanism. Use whichever is most convenient for you.
The key is to leverage Qt's built-in event loop mutex. When you're sending signals to objects living in a thread different from the sender, the signal gets converted into a QMetaCallEvent and is posted to the event queue of the receiving QObject. This is done in a thread safe manner of course, and all one has to do is to leverage it. Sending explicit events works the same way. The event loop spinning in the thread where the receiver lives simply picks up QMetaCallEvents and executes slot calls accordingly, or dispatches your events to your implementation of customEvent() method.
When you start a raw QThread, the default implementation of the run() method spins up an event loop. You'll notice that such a thread is effectively idle and does not consume any CPU resources: the event queue is empty, and the event loop is blocked, waiting for someone to post an event to its queue. Once you move some QObjects to such a thread, the queued signal-slot deliveries will be done via the event loop of that thread. It works the same whether it's the GUI thread, or any other thread. The GUI thread is not special in any way when it comes to receiving events or queued signals.