wxWidgets (or even OOP GUI) Multiple Windows - c++

I'm kind of stuck on something; regarding spawning multiple forms in OOP.
The message loop most of the time is (wxWidget's case) window->show();
bool MyApp::OnInit()
{
MainWindow *oWindow = new MainWindow(wxT("My Window"));
oWindow->Show(true);
return true;
}
Others have oWindow->run(), but anyway my question is:
I've created a second thread with the exact same structure of the function above and called the message loop method. The problem is that the window appears and dissapears suddenly which doesn't make sense to me. If however I call:
MainWindow *oWindow = new MainWindow(wxT("My Window"));
oWindow->Show(true);
MainWindow *oWindow2 = new MainWindow(wxT("My Window"));
oWindow2->Show(true);
It will work, but I don't want that as I will need to keep track of the windows I create and have them on separate threads. What can I do?

You cannot run wxWidgets windows in anything other than the main thread.
"GUI calls, such as those to a wxWindow or wxBitmap are explicitly not safe at all in secondary threads and could end your application prematurely. This is due to several reasons, including the underlying native API and the fact that wxThread does not run a GUI event loop similar to other APIs as MFC."
http://docs.wxwidgets.org/2.8/wx_wxthread.html
BTW, I cannot imagine any situation where what you want to do is a good idea. There is never any need to tun windows in more than one thread.
A windows program is event-driven. You can as have as many top level windows as you want, but there should be just one event queue so that the events on two windows do not end up in contention for the same resource. This is why wxWidgets prevents you trying to create two threads both handling windows events.

Related

How to have Qt embedded into another app (non-blocking way)

I am using a 3D rendering C++ API and want to use Qt to display GUIs on top of it.
My rendering API runs in the main() application thread, just like Qt wants.
At first I tried to run Qt in it's own std::thread and it worked perfectly fine - and I have no idea what Qt's doc means with
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread
https://doc.qt.io/qt-5/thread-basics.html
This is either plain wrong or poorly written...
My std::thread worker looks something like this:
int SomeClass::qt_app_worker(size_t width, size_t height, const std::string& title, const std::string& contents) {
int argc = 0;
QApplication app(argc, NULL);
// QDialog here
return app.exec();
}
The problem is then I can't do anything with this Qt app because if I try to create say another QDialog from the main() thread, Qt will complain I can only do this from the thread owning my QApplication (qt_app_worker).
So I'm either permanently locked out of the qt_app_worker thread, or I have to implement my own message queue for EVERYTHING Qt-related.
I sketched it with a derived QApplication class using startTimer() and then handling custom messages in timerEvent(...) but this is just too much hassle.
I just don't understand why Qt won't let a user run it in a separate thread, hopefully I'm just missing something.
There are (at least) two built-in thread-safe ways to communicate with the GUI thread (which is usually the "main thread" of Qt application, which is why it is often called main thread, and for Qt point of view it is).
You can post events (including your own custom event subclasses) to the thread using QCoreApplication::postEvent.
You can invoke methods of objects in another thread, provided you do so with Qt::QueuedConnection or Qt::BlockingQueuedConnection connection type using QMetaObject::invokeMethod (and its different overloads).
Communication the other way, from Qt to you own main thread, can happen in a few ways. I believe using Qt::BlockingQueuedConnection also allow getting a return value, but you probably don't want that blocking.... So you can just use any of the usual methods of communicating between threads, not limited by Qt, such as simply atomic or mutex-protected variables which are set from Qt, and your threads polls or otherwise reads when relevant (such as at start of every frame). Or make a simple message queue, if you want to be able to track every change and not just the state at the start of a frame or whatever.

Qt Gui not updated because of threading issue

I am using a third party library which takes 60-90 seconds to dynamically load several libraries. It is an unfortunate design choice, but I can't change who the built their code.
I am trying to use a QSplashScreen to at least tell the user to wait while I'm doing this one-time loading in the background. The problem is that the splash screen is not painting. I can see a window of non-painted space while the library loads. I can see the splash screen afterwards before I close it.
I looked at similar questions (e.g. Qt Splash Screen not showing) but nothing seems to resolve my problem. I have tried loading an empty QPixmap and just giving it a solid color. That doesn't show up either.
QApplication a(argc, argv);
QPixmap pxl("icon.bmp");
QSplashScreen qss(pxl);
qss.show();
qss.showMessage(QString::fromStdString("Please wait... Loading"));
a.processEvents();
MainWindow w;
//thread is blocked
w.preLoad();//this is where the lengthy process takes place
w.show();
qss.finish(&w);
I'd like to ensure that it at least paints once before I start my loading process.
------------------------EDIT-------------------------------
Let me reiterated that the call to preLoad is BLOCKING the thread. This is not an option. I have tried a separate thread for that process. I have tried with a separate thread for the splash screen as well (turning it on and then finishing whne the other thread is done). I have tried using semaphore between the two threads to accomplish this and while everything works (including the splash screen) it takes 200-800 seconds to load. That is simply not acceptable. Thus I would like to see if there is away around it from this perspective.
-------------------------Final solution--------------------------------
Thanks to the comments below I was made aware that Qt has its own threading functionality. All the problems I was seeing appear to be caused by the interplay of std::thread and Qt's own implementation.
I have a partial solution which does work. It's not as neat as it could be, but I wanted to include it in the question thread.
//in the main method code described above
MainWindow w;
w.preLoad();
while(w.IsLoading())
{
//waiting on semaphore signaling loading is complete
//this part could probably be done better with QThread
//and signals, but it is a quick fix for now
std::this_thread::sleepfor(std::chrono::milliseconds(500));
a.processEvents();
}
w.show();
qss.finish(&w);
//In the MainWindow class
void MainWindow::preLoad()
{
loading=true;//semaphore to stall main thread
QFuture<void> future = QtConcurrent::run(this, &MainWindow::LongMethod);
}
void MainWindow::LongMethod()
{
thirdPartyLibrary.impossibleCall();
loading=false;//this handles my semaphore
}
Every GUI is executed in an infinite loop, so Qt also uses it, but the blocking tasks generate that the loop is not executed correctly, showing inadequate behaviors like the one you observe.
If one wants to execute blocking tasks it is advisable to execute it in another thread for it Qt provides several possibilities:
QThread
QThreadPool and QRunnable
QtConcurrent
I recommend the following link for you to choose the right option for your case.
If you want to update the GUI view with the information generated in another thread it is advisable to use signals and slots, or use QtConcurrent.
GUI Thread and Worker Thread
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread. All widgets and
several related classes, for example QPixmap, don't work in secondary
threads. A secondary thread is commonly referred to as a "worker
thread" because it is used to offload processing work from the main
thread.
Another way is to force the GUI to update for this we can use qApp->processEvents().
References:
http://doc.qt.io/qt-5/thread-basics.html
http://doc.qt.io/qt-5/threads-technologies.html

How can I integrate new Qt windows with an existing X application?

I have an existing (large) X application based on raw XLib. I would like to add additional windows to this application using Qt 4. What is the best way to do this?
Research so far:
(If it matters for the details, I'm looking at Qt 4.7.4 right now.)
My existing application calls XtAppNextEvent in a loop to handle its events. What I am hoping to do is replace this event loop with a Qt-based event loop, let Qt handle its own events, and make calls to XtDispatchEvent for non-Qt events.
I have located the part of Qt that processes X events (in src/gui/kernel/qapplication_x11.cpp, QApplication::x11ProcessEvent). I believe the key part of this function is:
QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window);
which determines whether the event refers to a window that Qt knows about. For non-Qt windows, this returns NULL. There are a couple of processing exceptions after this, then a block like:
if (!widget) { // don't know this windows
QWidget *popup = QApplication::activePopupWidget();
if (popup) {
// ... bunch of stuff not involving widget ...
}
return -1;
}
What I was hoping was there would be an event callback at this point that was called for non-Qt related window events, so I could simply implement a virtual function in my derived QApplication and proceed with the application's existing event processing. I can add such a function and rebuild Qt, but I would rather avoid that if possible.
Am I on the right track with this, or might there be a better way?
I have found existing questions similar to this, but they're all for Windows (MFC or .NET). This is specific to X.
The solution I ended up with was to find a copy of the Qt Motif Extension (it's no longer available from Digia directly as it is now unsupported, but you can still find copies of qtmotifextension-2.7-opensource.zip). In there, the qtmotif.h and qtmotif.cpp modules show how to create a QAbstractEventDispatcher that handles X events for both Xt/Motif and Qt components.

Can I have multiple GUI threads in MFC?

I have a large MFC based application that includes some potentially very slow tasks in the main thread. This can give the appearance that the application has hung when it is actually working its way through a long task. From a usability point of view, I'd like to be giving the user some more feedback on progress, and have an option to abort the task in a clean manner. While hiving the long tasks off into separate threads would be a better long term solution, I'm thinking a pragmatic short term solution is create a new GUI thread encapsulated in its own object complete with dialog including progress bar and cancel button, used in a similar manner to a CWait object. The main thread monitors the cancel status via an IsCancelled method, and finishes via a throw when required.
Is this a reasonable approach, and if so is there some MFC code out there already that I can use, or should I roll my own? First sketch looks like this
class CProgressThread : public CWinThread
{
public:
CProgressThread(int ProgressMax);
~CProgressThread()
void SetProgress(int Progress);
BOOL IsCancelled();
private:
CProgressDialog *theDialog;
}
void MySlowTask()
{
CProgressThread PT(MaxProgress);
try
{
{
{ // deep in the depths of my slow task
PT.SetProgress(Progress);
if (PT.IsCancelled())
throw new CUserHasHadEnough;
}
}
}
catch (CUserHasHadEnough *pUserHasHadEnough)
{
// Clean-up
}
}
As a rule, I tend to have one GUI thread and many worker threads, but this approach could possibly save me a bunch of refactoring and testing. Any serious potential pitfalls?
Short answer, Yes, you can have multiple GUI thread in MFC. But you can't access the GUI component directly other than the created thread. The reason is because the Win32 under the MFC stores the GUI handler per thread based. It means the handler in one thread isn't visible to another thread. If you jump to the CWinThread class source code, you can find a handler map attribute there.
Windows (MFC) doesn't has hard difference between the worker thread & GUI thread. Any thread can be changed to GUI thread once they create the message queue, which is created after the first call related to the message, such as GetMessage().
In your above code, if the progress bar is created in one thread and MySlowWork() is called in another thread. You can only use the CProgressThread attributes without touch the Win32 GUI related functions, such as close, setText, SetProgress... since they all need the GUI handler. If you do call those function, the error will be can't find the specified window since that handler isn't in the thread handler mapping.
If you do need change the GUI, you need send the message to that progress bar owner thread. Let that thread handles the message by itself (message handler) through the PostThreadMessage, refer to MSDN for detail.

Gtkmm: Adding Window at later time

Because I´m writting a "generic" application behaving completely different when facing other configurations, I´m forced to show gtk windows even if I dont yet know them at startup. There might also be the requirement that multiple windows need to be visisble (not modal dialogs but standalone windows) at the same time. But, it would be great if one can simply start one gtk event loop at startup.
Is is somehow possible to add windows to that loop after it has been started?
While I found the Gtk::Application class which seems to support exactly the indented behaviour I´m restricted to use the Gtk::Main class.
There's only a single Gtk::Main object allowed. Widgets should be created in the same thread the main event loop is being run in. To work around this limitation you need to develop a way to pass your window creation commands to the gtk thread.
The simplest way is to use Glib::Dispatcher
struct WindowBuilder {
/**/
Glib::Dispatcher* signal_create;
void create_window() {
//From main thread...
signal_create->emit();
}
}
void create_mainWnd() {
new Ui::MainWnd();
}
//From Gtk thread...
builder->signal_create->connect(sigc::ptr_fun(create_mainWnd));
Gtk::Main::run();
Glib::Dispatcher doesn't take any arguments with it, so next step is to figure out how to pass arguments around between threads.
For different types of windows you can just use different disptachers.
boost::asio::io_service can help you pass messages around.
while(!exit) {
io_service.reset();
io_service.poll();
while(Gtk::Main::events_pending())
Gtk::Main::iteration();
Sleep(0);
}