I am trying to create this QT gui using a thread but no luck. Below is my code. Problem is gui never shows up.
/*INCLUDES HERE...
....
*/
using namespace std;
struct mainStruct {
int s_argc;
char ** s_argv;
};
typedef struct mainStruct mas;
void *guifunc(void * arg);
int main(int argc, char * argv[]) {
mas m;<br>
m.s_argc = argc;
m.s_argv = argv;
pthread_t threadGUI;
//start a new thread for gui
int result = pthread_create(&threadGUI, NULL, guifunc, (void *) &m);
if (result) {
printf("Error creating gui thread");
exit(0);
}
return 0;
}
void *guifunc(void * arg)
{
mas m = *(mas *)arg;
QApplication app(m.s_argc,m.s_argv);
//object instantiation
guiClass *gui = new guiClass();
//show gui
gui->show();
app.exec();
}
There appears to be two major issues here:
The GUI is not appearing because your main() function is completing after creating the thread, thus causing the process to exit straight away.
The GUI should be created on the main thread. Most frameworks require the GUI to be created, modified and executed on the main thread. You spawn threads to do work and send updates to the main thread, not the other way around.
Start with a regular application, based on the Qt sample code. If you use Qt Creator, it can provide a great deal of help and skeleton code to get you started. Then once you have a working GUI, you can start looking at adding worker threads if you need them. But you should do some research on multithreading issues, as there are many pitfalls for the unwary. Have fun!
Related
Hey this should be a pretty straightforward question. Simply put:
Want to run a function in another thread.
Need to wait for the function to finish.
Do not want to freeze the thread though while waiting.
In other words, I'd like to use an eventloop.
Here is the freezing example:
extern void sneed()
{
QEventLoop wait;
wait.exec();
}
int main( int argc, char *argv[] )
{
QApplication a(argc, argv);
{
// this starts a tui
QConsoleToolkit::s_CursesController.start( QCD::CursesEngine::Engine_Thread_Stdout_Monitor );
}
ct_Start( "Sneed" );
QFuture<void> ff = QtConcurrent::run(sneed);
ff.waitForFinished(); // This freezes the tui
ct_Finish( "Chuck" );
}
I tried to use a QEventLoop in the main thread instead of ff.waitForFinished(), but I could not figure out how I could emit a signal when ff was finished, because QFuture isnt a QObject, and has no finished signal that I could bind to:
https://doc.qt.io/qt-6/qfuture.html
I tried passing a QObject via reference to emit a signal from it instead, but couldnt get it to compile.
What am I missing here?
The solution comes from a simple class called QFutureWatcher:
doc.qt.io/qt-5/qfuturewatcher.html
Here is some sample code for running lambda's in a different thread, and receiving its value.
template <class T>
auto asynchronous( auto &&lambda )
{
QEventLoop wait;
QFutureWatcher<T> fw;
fw.setFuture( QtConcurrent::run(lambda) );
QObject::connect ( &fw, &QFutureWatcher<T>::finished, &wait, &QEventLoop::quit );
wait.exec();
QObject::disconnect( &fw, &QFutureWatcher<T>::finished, &wait, &QEventLoop::quit );
return fw.result();
}
using the function would look like this:
int n(0);
ct_Start(n); // 0 - Running in main thread
n = asynchronous<int>([&n](){
// Running in background thread.
// Mainthread is waiting for this lambda to finish
// but mainthread is not locked.
// User Interface will still function.
for ( int i = 0; i < 100000; i++ ){
ct_Debug(n++);
};
return n;
});
ct_Finish(n); // 100000
Note: ct_Debug ct_Start ct_Finish are not found in the Qt framework. They are debugging macros for a TUI.
I think you misunderstood my comment. This really is just a follow-up comment. It's not a real answer because I'm not a Qt expert, but I posted it as an "answer" so that I could include a code example.
The question that I tried to ask in my earlier comment was, why can't you do this?
extern void sneed() {
...
}
void sneed_wrapper() {
sneed();
...emit a signal...
}
int main( int argc, char *argv[] )
{
...
ct_Start( "Sneed" );
QFuture<void> ff = QtConcurrent::run(sneed_wrapper);
...
}
You said that you could solve your problem if the thread that runs sneed() would send a signal that would alert the main event loop when the thread ends.
OK, so why not have the thread run sneed_wrapper() as shown above? sneed_wrapper() runs sneed() and then when sneed() is finished, it can do whatever it takes in Qt* to send the signal that will alert the main loop.
* Did I mention that I don't know Qt?
OP here. To elaborate, you could make your example work using global QObject. [So by this metric, this is also a potential answer]:
SomeObject o;
extern void sneed() {
...
emit o.finished();
}
int main( int argc, char *argv[] )
{
...
ct_Start( "Sneed" );
QEventLoop wait;
QFuture<void> ff = QtConcurrent::run(sneed);
QObject::connect( &o, &SomeObject::finished, &wait, &QEventLoop::quit );
wait.exec();
ct_Finish( "Sneed" );
}
You may ask, why not pass a local QObject by reference or by pointer? I tried that, but was not able to get the program to compile.
I am trying to create a custom GMainContext* (so not to conflict with Qt/etc) and process the loop on a custom thread.
I am using libnm (for NetworkManager), but I don't think it is relevant.
The signal handlers aren't raised/processed when using a custom GMainContext*.
#include <NetworkManager.h>
#include <iostream>
#include <thread>
// Uncomment this for it to not work.
#define WORKING
static void test_callback ()
{
std::cerr << "test callback";
}
static int thread(GMainContext *mainContext)
{
GMainLoop* mainLoop = g_main_loop_new(mainContext, FALSE);
g_main_loop_run(mainLoop);
}
int main(int argc, char *argv[])
{
#ifdef WORKING
GMainContext* mainContext = g_main_context_default();
#else
GMainContext* mainContext = g_main_context_new();
g_main_context_push_thread_default(mainContext);
#endif
GError* error = nullptr;
NMClient* client = nm_client_new(nullptr, &error);
g_signal_connect(client, NM_CLIENT_ACTIVE_CONNECTION_ADDED, G_CALLBACK(test_callback), nullptr);
g_signal_connect(client, NM_CLIENT_ACTIVE_CONNECTION_REMOVED, G_CALLBACK(test_callback), nullptr);
std::thread thread_obj(thread, mainContext);
thread_obj.join();
return 0;
}
The signal handlers are properly raised with WORKING defined, using g_main_context_default().
I suspect this is because at least some of the underlying libnm GSources are still being added to the global default GMainContext (the one always returned by g_main_context_default()). If you’re going to run a custom GMainContext in another thread, you need to ensure that all GSources are attached to it; or you need to also run the global default GMainContext in the main thread.
If you are trying to run the GMainContext in one thread and a Qt main loop in the main thread, you are going to have to do a lot of thinking about the thread safety of data which is touched by both of them. It may be easier in the long run to chain the global default GMainContext to the Qt main loop (or vice versa) so that you only have one event loop running (in one thread). Then you don’t have to think about thread safety.
in my program I am running a thread that gets some values from a device and then these values need to be displayed on the UI. To realize this I am using an std::thread in order to have a cross platform program. Now the problem is when the thread is running (it could take up to 3 minutes before finishing) and I want to notify the UI thread (to update UI elements) in order to display the values that are already available. I know that this could be achieved with PostMessage(...) but it would require using winapi. So is there a way to achieve this without using winapi ? Here is a simplification of the code that represents what I would like to do.
#include <thread>
MyClass {
public:
// Some initializations
std::thread t;
void LoadingParams();
}
void MyClass::Init() {
// Some initializations...
t = std::thread(&MyClass::LoadingParams, this);
// ...
}
void MyClass::LoadingParams() {
for(int i=0; i < NB_VALUES; i++) {
int value = ReadValue();
// TODO: Send notification to main thread to display the value
// Alternative to PostMessage
}
}
So the idea would be to replace the TODO with the notification function.
I'm building a small game.
One of the input options is to restart the game. The only way I could think of doing this was to call the main function from within the main function
int main(int argc, char argv[]) {
...
if (input == "restart") {
main(argc, argv);
}
Is this bad form? Will it even work?
No, the C++ standard disallows calling main manually.
To cite the standard (C++11: 3.6.1 Main Function)
The function main shall not be used within a program. The linkage
(3.5) of main is implementation-defined.
A program that defines main as deleted or that declares main to be inline, static, or constexpr is ill-
formed. The name main is not otherwise reserved.
You can't call main() recursively. That's actually undefined behavior.
Use a loop instead:
int main() {
bool restart = false;
do {
// Do stuff ...
// Set restart according some condition inside of the loop
if(condition == true) {
restart = true;
} // (or simplyfied restart = condtion;)
} while(restart);
}
Do not do this. From http://en.cppreference.com/w/cpp/language/main_function
The main function has several special properties:
1) It cannot be used anywhere in the program
a) in particular, it cannot be called recursively
Since recursively calling main is impossible in C++ and would not really solve the problem, here's my 2 cents on how to deal with the problem:
Basically, any large program is a loop that might look like this:
int main()
{
bool quit = false;
//Initialise and aquire resources...
while (!quit)
{
//Run game and set quit if user wants to quit...
}
//free resources, should be automatic when RAII is adhered.
}
Your game should already look something like this, since any program that is not a loop will immidiately quit and won't be much of a game. Just change the structure to this:
int main()
{
bool quit = false;
bool restart = false;
while (!quit)
{
Restart = false;
//Initialise and aquire resources...
while (!quit && !restart)
{
//Run game and update quit and restart according to user input.
}
//free resources, should be automatic when RAII is adhered.
}
}
you can use GOTO but this is not a good way of programming in general. As the guys mentioned to use booleans or loops to check the current state or any other way instead of goto because it causes sometimes problems in the compiler. However it is still available in C and not C++ (AFAIK)
If in addition to reloading internal resources, you also need to reload external things like a libraries that the game links to you can do this by re-launching the game in a thread, detaching the thread and then shutting down.
I use this in a game I've made where I have automatic updates, to start the new updated executable and libraries.
int main() {
//initialize the game
bool restart=false, quit=false;
while (!quit) {
//Main loop of the game
}
if (restart) {
#ifdef _WIN32
std::thread relaunch([](){ system("start SpeedBlocks.exe"); });
#elif __APPLE__
std::thread relaunch([](){
std::string cmd = "open " + resourcePath() + "../../../SpeedBlocks.app";
system(cmd.c_str());
});
#else
std::thread relaunch([](){ system("./SpeedBlocks"); });
#endif
relaunch.detach();
}
return 0;
}
A bit of a hack, but it gets the job done. The #ifdefs just make it use the correct launch cmd for Windows/Max/Linux.
I would like to visualise a running calculation in another thread with the visualisation tool kit in real time. The calculation spits out a new set of values to be visualised each iteration and the graphical thread must some how know this and load the new values.
One way to do this would be to have the main thread poll the state of the calculation. Ideally I'd not like to do any polling but if there is no other way then I will.
The best way I can think of would be to have the the calculation thread push an event onto the main thread's event queue every iteration of the calculation which is then processes by the GUI. I'm not sure how to go about doing this, or if it can be done in a thread safe manner.
I'm using vtk in gcc/C++ on linux using pthreads.
Listen to the Modified event on the object you're interested in, in the main thread using a vtkCommand (or appropriate derived class). You can then update your renderer and associated classes when the callback occurs.
But many VTK classes aren't thread-safe. You'll need to pause updation while rendering occurs. Otherwise, it'll segfault while trying to read and write the same memory.
I think it is a standard way. Create separate thread for window handling (i.e. window messages processing), and sometime put data into window (i.e. update the image).
Similar procedure with MathGL looks like following (see How I can create FLTK/GLUT/Qt window in parallel with calculation?)
//-----------------------------------------------------------------------------
#include <mgl/mgl_fltk.h>
#include <pthread.h>
#include <unistd.h>
mglPoint pnt; // some global variable for changable data
//-----------------------------------------------------------------------------
int sample(mglGraph *gr, void *)
{
gr->Box(); gr->Line(mglPoint(),pnt,"Ar2"); // just draw a vector
return 0;
}
//-----------------------------------------------------------------------------
void *mgl_fltk_tmp(void *) { mglFlRun(); return 0; }
int main (int argc, char ** argv)
{
mglGraphFLTK gr;
gr.Window(argc,argv,sample,"test"); // create window
static pthread_t tmp;
pthread_create(&tmp, 0, mgl_fltk_tmp, 0);
pthread_detach(tmp); // run window handling in the separate thread
for(int i=0;i<10;i++) // do calculation
{
sleep(1); // which can be very long
pnt = mglPoint(2*mgl_rnd()-1,2*mgl_rnd()-1);
gr.Update(); // update window
}
return 0; // finish calculations and close the window
}
//-----------------------------------------------------------------------------