Is there a way to pass the wxWidget GUI to a wxThread? - c++

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

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.

How to Run an event while another event is running in wxWidgets GUI?

I created one GUI having two buttons. one is start button and the other is stop button. when start is pressed the program will execute in the background and the gui will freeze. I couldn't control the window anymore. even a mouse click is not responding. the stop button is for stopping the program. since the window is not responding as it is running the program i cant press stop. what is the possible solution? .please help
A thread is sort of a subprogram inside your program. When the application starts it runs in the main thread. You can create many other threads; all of them (the main one included) share the application memory space (for example, same global vars in scope).
There are two kind of threads: "detached" and "joinable". detached threads delete themselves when they finish, think of them as "fire and forget". Conversely, joinable threads are deleted by yourself, only after they have completed their job.
In wxWidgets all GUI is executed in the main thread. Calling a GUI function from another thread is a nightmare, don't do it.
Your case is a typical situation. The "start" button launches a thread to do some job. If you want to cancel this job you push the "stop" button.
How to instruct the thread to cancel its job?
While you can use wxCondition, you can also set a flag on your own. The working thread reads at some moment this flag (it's not automagic, you must code it) and stops or continue depending on its value. Don't forget to use a wxMutex before accesing the flag to protect it from another thread changing it at the same time.
Also, threads can post messages to the main thread event-loop. This way you can tell the main thread that your worker thread has finished its job.
Threads require more attention when you're coding them. You must avoid some situations such as:
"dead lock": two threads wait one for each other, none finishes.
"race condition": several threads try to change a shared value at the same
time.
More on wxWidgets docs and thread sample.
Finally, C++11 has std::thread and other related friends (mutexes, semaphores, etc). It's your choice to use it instead of wxWidgets classes.

Simulation loop with Qt

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.

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.

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.