Simulation loop with Qt - c++

I have to create a cookie factory simulation program for an assignment. The program's GUI uses normal Qt widgets (such as: labels, buttons, and line edits) to control the simulation variables and objects. I already created the GUI, but I don't know how to do the simulation.
Our teacher suggested using threads (one per machine). I read on QThreads, but got the impression (from this link) that they are not really ideal for accessing objects from other threads, and I don't really know how to create or handle them.
However, the simulation is simple enough that (I believe) it could be done with only one loop (one thread), but I don't know how to create this loop in the QMainWindow class.
So, my main question is: How can I run a loop that can access the GUI, can be accessed by the GUI (so that it can change machines' values), and can access the machines? I just don't really know how to connect the GUI and the simulation.
Thanks, sorry for the long post.
Edit #1: Pseudo-code of what I am trying to do:
// Machines' initialization:
rawMaterialsTransport = new RawTransport();
doughMachine->conveyour = doughConveyour;
// Simulation loop:
lastTime = 0
while(running) {
// Handle pauses.
while(simulationPaused) {
sleep(100);
}
// Update machines/do the simulation
timePassed = now() - lastTime
lastTime = now()
rawMaterialsTransport->update(timePassed);
doughMachine->update(timePassed);
chocolateMachine->update(timePassed);
doughConveyour->update(timePassed);
// Update the GUI
chocolateGramsProcessedLabel->setText(to_string(chocolateMachine->gramsProcessed()));
// Sleep so as to not waste
sleep(100);
}
// On the GUI side:
onLineEditEnter() {
doughMachine->gramsPerSecond = double(lineEdit->text);
}
onPauseButtonPress() {
simulationPaused = !simulationPaused;
}

You could use signals and slots.
In the GUI, you connect the signals emitted by your GUI items (the buttons, line edits, etc.) to a custom slot which does the business logic. For example buttons emit the clicked signal when pressed.
If the processing of the business logic in the slot has terminated, you emit another signal that is connected to a slot in your widget which updates the GUI.
If the GUI hangs, i.e. the processing of the business logic takes too much time, you have to start another thread for doing the business logic.
Signals and slots also work across threads.
References
The signals and slots documentation.
The documentation of the connect methods.
The list of signals a QAbstractButton emits.
Signals and slots across threads. This page also contains references to examples.
Blocking Fortune Client Example where a thread runs in a loop.

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.

qt - setText outside of paint events not ok?

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.

Is there a way to pass the wxWidget GUI to a wxThread?

I have made a game that uses a game loop.
Now i am trying to implement a GUI for this game in wxWidgets.
The problem is that when I initialize the GUI the control of the program remains on a GUI loop and doesn't go to the game loop.
So, can i make the GUI run on its own thread?
You can, but leave all code, which interacts with the GUI on the main thread/EDT (Event Dispatch Thread). Concurrent access to GUI elements is not intended by design and will cause problems. Instead, put the game loop into a wxThread and fire appropriate events from there. Those events can then be handled on the EDT to update the GUI or for rendering a frame.
Another solution would be, to invoke single iterations of your game loop on the main thread, using wxTimer.
Note:
Throttle the game loop or coalesce the events if necessary. wxTimer does perfectly support throttling by frequency and coalescing of update events. In a separate thread, you'd need to sleep for the remaining time of the desired cycle/iteration time or wait on a semaphore, triggered by the main thread.
Implement access to share data like the game state with a synchronization object like wxMutex. Preferably, you could instead use std::mutex and std::thread from C++11.
Examples:
http://wiki.wxwidgets.org/Inter-Thread_and_Inter-Process_communication
http://wiki.wxwidgets.org/Making_a_render_loop

qt threads worker design with blocking while loop

i using qt5 and opencv to create an application that give a user inteface using qt and does the image processing part in opencv.....
so far my design is:
i am displaying a video and some standard controls like buttons and checkboxes using qt main gui thread
for capturing image and processing it, i have created a worker class derived from QObject and moved it to a thread....
the function that is executed in the worker class(Worker::process) has a blocking while loop.....that constantly:
captures a frame from a video or a camera
does some processing on it
converts from cv::Mat to QImage
emit a signal to the main thread to display the QImage
also in order to recieve user input i was using emitting signal from the main thread to the worker slots
the problem i faced was that the signal from the main thread never got picked off by the worker because of the event loop blocking while loop.
after much searching i came up with the solution to use Qt::DirectConnection argument while connecting the signal from the main thread to the worker slots. that solved the problem at that time.
now i need to add a qtimer or qbasictimer inside the blocking while loop....and guess what, the timer slot(in the case of qtimer) and the protected timerEvent handler (in the case of the qbasictimer) never get called. my hunch is that again the blocking while loop is the culprit
after much searching and reading on forums i have come to the conclusion that somehow my over all design maybe incorrect.....and as i keep adding more functionality to my application these problems will keep showing up.
I have two options now:
somehow call the threads exec() function inside the blocking while loop. so the question to the gurus out there is:
"how do i call the thread::exec() method inside a worker QObject class, i need the reference to the thread running the worker to call exec()" (short term solution)
change the whole implementation.....and here the questions is:
"what are my options....." (long term)
please feel free to ask for details in case my wording or english has made the problem unclear in any way.....thanks...
Inside your worker's blocking loop, call qApp->processEvents(); periodically.
http://qt-project.org/doc/qt-5.1/qtcore/qcoreapplication.html#processEvents
#include <QApplication>
// ...
void Worker::doWork()
{
while(true)
{
someLongImageProcessingFunction();
qApp->processEvents();
}
}
This should allow for the slots to get processed, and for the timers to update.
Using a direct connection may let you access and change values local to your worker, but you should be careful about thread safety. If you put a QMutexLocker right before your values that get modified by your GUI and right before your worker thread uses them, you should be good.
http://qt-project.org/doc/qt-5.1/qtcore/qmutexlocker.html
Also if you wanted any of those slots to run on the worker thread, you need to use the QueuedConnection.
http://qt-project.org/doc/qt-5.1/qtcore/threads.html
http://qt-project.org/doc/qt-5.1/qtcore/qthread.html#details
In some parts of the Qt docs it describes subclassing the QThread class. Other parts recommend the Worker/Producer model, and just use connections to setup how you use your threads. Usually there are fewer gotchas with the Worker/Producer model.
Hope that helps.

Best strategy to update QTableView with data in real-time from different threads

I have application that for now starting few threads ( like 5 – 10 ) to collect data from different source .
They are separated from the main GUI thread so I don’t feel any slowness in the GUI and I can keep working while the background threads are working . all great .
But now I like to be able to display the results in QTableView in my main GUI . the data is strings allots of them and it can have between 10,000 to 100,000 results that supposed to be upto 100,000 rows in the QTableView.
My question is what is the best way to update the Table in the Main GUI from the threads so TH GUI won’t be slow or idle while updating.
This is how I would do it:
Add a signal to the worker threads that is emitted each time a new batch of data is ready. Connect this signal to a slot defined in the main GUI thread using Qt::QueuedConnection. This slot should collect the processed data from the worker threads and insert it into the table's model. Model should be naturally also in the GUI thread.
Update 1
More detailed explanation. You already got the threads down so all you'll have to do is to expand them a little. Example:
// NOTE:
// In this example I'm assuming that the thread continues to work after
// preparing first batch of data. One thread can prepare multiple batches
// over time. If that's not the case for you then you can probably
// safely ignore mutex stuff and intermediary tmp variables.
class MyWorker : public QThread
{
// ...
public:
void run()
{
while (bWork)
{
QList<MyData> myData;
// Populate 'myData' variable with your data.
// ...
// Now, store myData in more persistent buffer and emit the
// ready signal.
dataBatchMutex.lock();
dataBatch.append(myData);
dataBatchMutex.unlock();
emit dataBatchReady();
}
}
QList<MyData> popLastBatch()
{
QMutexLocker l(&dataBatchMutex);
QList<MyData> tmp = dataBatch;
dataBatch.clear();
return tmp;
}
signals:
void dataBatchReady();
private:
QMutex dataBatchMutex;
QList<MyData> dataBatch;
};
We have the worker thread. Now about the GUI thread:
Create your worker threads objects.
Connect the dataBatchReady() signal to a slot in the GUI thread. Remember to use Qt::QueuedConnection.
Start the threads.
When that slot is executed you need to figure out which worker thread has the new data. You may pop them all (not very efficient) or you may add additional method to the worker to find out if the dataBatch field is not empty. You may also invent other way to figure out which thread emitted the signal - that's up to you to figure out.
When you figure out the thread just call the popLastBatch() on that thread and add the returned list to the model. The model will take care of the rest. If you still have performance issues then refer to tHand's response.
Note: I didn't test the code so it may contain some obvious errors. You should get the idea, though.
Your performance problem may be related to actions performed by the control as each row is added.
For example see:
QTableView is extremely slow (even for only 3000 rows)