tags:

views:

995

answers:

2

Greetings overflowers. I am trying to add a GUI to to an existing project. More specifically to a plugin that is loaded as a .so file (or when compiled on win32 a .dll)

The project has its own threading implimentation already to deal with portability. I know that QT has its own cross platform threading model but it would be preferable to stay within this existing threading model.

My question to the QT veterans out there [I have only just started reading the docs] is: Would it be possible to embed a GUI using QT in to a plugin as described above? The plugin already is a command line interface and I would like to have the GUI optional, even if its compiled in. Since those standard functions get called by the main program, the GUI (which I assume will live in another thread) will have to be accessable or able to have methods called on it so that the CLI thread can coexist and the standard functions can work with any permutation of the two interfaces.

edit 1:

after playing with the code a bit I am able to launch a simple GUI from the plugin. The plugin already is the CLI and has functions that are called from the main program. I simply created a new thread on initialization of the plugin and launched the blocking GUI from there:

QApplication app(NULL, NULL);
window = new zGui;
window->show();
app.exec();

The question here is: Is it possible to communicate with the GUI or rather access GUI elements from the CLI thread?

edit 2: some results

Alright, so far starting the blocking GUI in a seperate thread has worked with no problems. I am able to access widgets in the GUI from the main plugin thread as well. I understand that this practice is discouraged as not only per the answers I've recieved so far but also the QT libs are spitting out some warning about unsafe access by another thread.

As of now I have only been working in a linux environment, perhapse real issues will be presented on other systems. I have seen only one glitch that I can not say for sure is related:

Upon changing the the max and min values of a progress bar widget, the progress bar appears blank. I was able to apply a simple fix to this by the following

//here is me setting the values
window->progressBar->setMaximum(character.maxHP);
window->progressBar_2->setMaximum(character.maxMP);
window->progressBar->setValue(character.curHP);
window->progressBar_2->setValue(character.curMP);

//and here is the fix
window->progressBar->setVisible(false);
window->progressBar->setVisible(true);
window->progressBar_2->setVisible(false);
window->progressBar_2->setVisible(true);

I suppose my final question is 'What specifically are the situations where accessing a QT GUI from an other thread is unsafe and why?'

+3  A: 

You can use a Qt GUI from a dll or so that is called from a non-Qt application, but it cannot be from a secondary thread, it has to run in the main thread. And the application event loop is started via a blocking method that returns when the GUI is closed out, so if you needed to have logic running in your app that is independent of the GUI, then that logic would need to be running in a secondary thread.

If you felt ambitious, you could modify the QCoreApplication and QEventLoop classes in such a way that you can manage the event loop from your calling application, and it probably wouldn't be all that difficult. But as far as I know there's no way to do it with Qt out of the box.

Gerald
as of this moment i have plugin's main thread as the already existing CLI and am able to start a new thread that launches a GUI [will explain above]
C-o-r-E
With extensive use you'll eventually run into problems doing that, but if it works for what you use it for I suppose there's no harm in it. It's generally not a good idea to access the GUI elements directly from a separate thread, your best bet is going to be using the events mechanism via QThread::postEvent or the signal/slots mechanism, with QueuedConnection type. If you compiled it with Qt 3 backward compatibility you could also use the Qt library mutex lock and access the widgets directly, but that can get a little dicey.
Gerald
+2  A: 

Consideing to Gerald answer, might I suggest that its better to keep the CLI (your app) separate from your apps GUI (ergo, a separate app).

Make your GUI app use the cli in the background. its easily done by using QProcess.

cheers!

Here Be Wolves