I am currently coding a program in C++/ Qt 5.9 to control a 3D Printer.
I have divided the project into several libraries :
The GUI Lib: The view
The Device Lib: Control each device (movement, printing tool, sensors)
The Controller Lib: Links the View with the Device lib
etc...
My problem is that I do not know how to initialize and terminate properly the execution of the program. More specifically, the Device library has a class named DeviceManager with two functions :
initialize() : which connect to each device and initialize them. This actions can take several seconds (10s for example)
finalize() : which closes all the connexions, can also take several seconds
What I would like to do is initialize the Device Lib in the right place without blocking the GUI and then finalize it in the right and not block the GUI
This is my main code :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
My solution now is to call DeviceManager::initialize() in the MainWindow constructor and DeviceManager::finalize() in the MainWindow::closeEvent().
The problem: even if I use concurrency to initialize and finalize in a different thread, the application displays its window several seconds after it was launched and the display freezes when the application is closed because it has to wait for the finalize function to be done.
How should I properly handle this initialization and finalization problem, please ? Do I need to reimplement the QApplication class? Do I try and do it in the main? Do you know any great example of an open source application doing that kind of initialize and finalize work?
The problem: even if I use concurrency to initialize and finalize in a different thread, the application displays its window several seconds after it was launched and the display freezes when the application is closed because it has to wait for the finalize function to be done.
You could start the initialize() function as own detached thread before starting the MainWindow. This could cause problems if the initializing thread doesn't terminate before the first initialized "thing" is needed. Something like:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
std::thread{initialize}.detach();
MainWindow w;
w.show();
finialize();
return a.exec();
}
To prevent the problem, and maybe lock some function in the GUI, then you probably need to have a state variable that it sets under a mutex on its way out, and which you examine under a mutex to see if it has been set.
Related
How can I totally remove the QApplication instance, so it can be possible to recreate it again in a sheared library.
If I have such a following code:
int main(int argc, char ** argv) {
QApplication *app = new QApplication(argc, argv);
MyWindow dialog;
dialog.show();
app->exec();
return 0
}
I want to be able to delete the instance after quiting the app (closing the application after app.exec())
I have tried to do the following:
app->setQuitOnLastWindowClosed(false);
app->quit();
delete app;
But non of them could be worked. I want to remove the QApplication instance like I did not create before.
The QApplication in my shared library always works if I did not define the QApplication in the main.
The library (lib) and the main application (app) are using different copy of Qt.
I am developing the app, the lib is imported to my app.
After closing the first dialog, I am using an event to trigger the thread in the library which it is waiting for this event.
You don't need to do that, because QApplication can only ever be created in the main thread. If the library and the main executable share the same Qt library, presumably the main application already created the QApplication object and will run the event loop for you. So the only thing you need to do in the library is to create some objects and the event loop will process their events.
If the main executable doesn't use Qt, then you should create the application in the main thread, prime its event loop, and let the native event loop dispatch events for you.
Alas, to directly answer your question: presumably you want to do some stuff after app.exec() returns. Your code could simply be, then:
int main(int argc, char ** argv) {
{
QApplication app{argc, argv};
MyWindow dialog;
dialog.show();
app.exec();
}
doSomething();
}
If I close the first dialog, the event loop will be left. Is it possible to keep the event loop?
Yes. You could clear the Qt::WA_QuitOnClose attribute of the first dialog. Or, preferably, set it on your dialog - the application won't quit as long as there are any dialogs with QT::WA_QuitOnClose still open.
Thus, for the second dialog, call:
secondDialog->setAttribute(Qt::WA_QuitOnClose);
Alternatively, if you don't have a pointer to the dialog, you can iterate all top-level widgets and clear (or set) the attribute on all of them:
for (auto widget : qApp->topLevelWidgets())
widget->setAttribute(Qt::QA_QuitOnClose, false);
I have created a set of watcher/helper classes that monitor an outside application, and I would like these to print to a log window inside my MainWindow's ui when changes are made. My idea was to create this watcher inside a thread in main, but I am not sure the best way to link it to my MainWindow. I know that simply passing it as below will not work, but am unsure of the proper way to do this, if there even is one, because of Qt's design. Some research indicated to me that it isn't really appropriate to pass MainWindow to an outside class, but I am unsure of a better way to do it.
int main(int argc, char *argv[])
{
try {
std::string host = "localhost";
unsigned short port = 8193;
MainWindow w;
w.show();
// Access class for the program that I am watching
UserInterface ui(host, port);
// StatePrinter class, which is registered in the UI and will print changes to MainWindow, ideally
// would I be able to pass something in the StatePrinter constructor to accomplish my goal?
ui.registerObserver(new StatePrinter(w));
UiRunner runner(ui);
boost::thread runnerThread(boost::ref(runner));
w.show();
QApplication a(argc, argv);
runner.cancel();
runnerThread.join();
return a.exec();
} catch(std::exception &ex) {
// ...
}
}
I suppose it is a possibility to make this thread inside MainWindow itself, but I prefer having it in main. What would be the best way to link my StatePrinter class to MainWindow?
You could make your watcher class a QObject itself, push it into a thread, and make it emit signals when it "notices" changes that you want to log with the log informations as the signal parameters.
Then, you could push this object in a QThread as follow :
QThread* thread = new QThread();
ui->moveToThread(thread);
//Create the needed connections
thread->start();
Depending on what you need, you may connect a signal to the thread's start() slot instead of calling it directly. (Read this to know which connections you'll need with your thread so it is started, stopped and cleaned correctly).
You have several problems:
Creating widgets before instance of QApplication
runnerThread.join call will block main Qt thread before entering Qt event loop - so your GUI will be freezed
You should implement notification system to watch for termination of boost threads. But better solution is to use Qt threads.
You should create first class - "watcher" with neccessary signals.
Then create second class with UI logic and neccessaty slots
Then connect signals to slots
Profit!
Look at Qt documentation about QThread - there are simple samples.
Do I miss any Qt functionality if I substitute QApplication::exec() with standard Windows message loop implementation? This should clarify what I mean:
The ususal “Qt” way to run event processing:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
return a.exec();
}
“Windows” way to run event processing:
#include <Windows.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Window w;
w.show();
MSG msg;
while(GetMessage(&msg, 0, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
The above demonstrates having external message loop with respect to QApplication instance, while QApplication instance itself doesn’t even have its own event loop at all.
In other words, if I have main.exe program (knowing nothing about Qt) with message loop and a .dll with Qt GUI and QApplication instance inside, will it be ok to let the external message loop from main.exe to handle events for Qt GUI?
Thanks in advance!
EDIT 1:
I’ll just answer myself in case it’s usefull for somebody:
We have a main .exe module written in C# under .NET that runs event loop processing, and we have a couple of .dlls written in Qt/C++ that have a GUI “inside” (and a QApplication instance that is shared). QApplication::exec() is never called but all the events are successfully dispatched by the main .exe (.NET) module’s event loop and all the Qt functionallity is present( signals/slots, threads, etc.)
EDIT 2:
That worked for Qt 4.8.2 but for Qt 5.1.0 things are a little bit different. Now you have to call QApplication::processEvents() once because it performs some initial initialization on its first call( installs WindowsHook on GetMessage or PeekMessage ). And after that whoever calls GetMessage in your application Qt events get processes and you are golden :)
The first thing which comes to my mind is that calling slots across threads won't work because the Qt event loop is executing those calls.
But the more important question is probably: Why do you want to do it like this especially since in qeventdispatcher_win.cpp is doing essentially the same thing?
I'm working on an OpenGL-based game using QGLWidget as a front-end. But due to all of the unnecessary overhead (plus having to distribute the heavy QT libraries!) I plan to migrate to GLUT, and am in the process of replacing 'Qt-stuff' with more standard alternatives before the big leap.
To replace the QTimers that control the framerate and fps timer, I'm trying to wedge those functions into a simple loop that replaces the app.exec() call, as follows:
//main.cpp
#include <QApplication>
#include <windows.h>
#include "mainwindow.h"
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow mainWin;//only contains a glwidget
mainWin.show();
do {
app.processEvents();
//call draw functions/fps based on system tick count
//...
Sleep(10);
} while (!app.closingDown()); //<-- this doesn't terminate
return 0;
}
So far it works fine during runtime, however once you try to close the window (via the system 'X' button), the window goes away but the program hangs in the background. The problem is that I can't find a static flag or query function that indicates that exit() or close() has been called. bool closingDown() always seems to be false, and I've tried toggling a static flag in the ~MainWindow destructor and detecting that, but that doesn't work either since that isn't called until main ends. I know I could probably do it by tying into QApps' aboutToQuit() signal, or maybe making a derived class from Qapp, and intercepting it, but that kind of defeats the purpose of moving away from signals/slots. Is there a simple way to tell if a QApplication has been ordered to shut down, from outside of the class?
You can reimplement
void QWidget::closeEvent ( QCloseEvent * event )
method to set your static flag. That method invokes for close events from window.
I recommend adding app.sendPostedEvents(); before that QApplication::processEvents() call. It may actually fix your problem, but if not, you can at least use event handlers as mentioned by #dzhon.
Nitpick: Qt is generally not formatted in all-caps. Saying 'QT' makes it appear as if you are talking about QuickTime!
I have the following source code:
Processmethod()
{
QDialog *ProcessMessage = new QDialog;
Ui::DialogProcessMessage Dialog;
Dialog.setupUi(ProcessMessage);
ProcessMessage->setModal(true);
ProcessMessage->setAttribute(Qt::WA_DeleteOnClose);
ProcessMessage->show();
PROCESSES START
}
After I want to show the QDialog "ProcessMessage" there are three QProcess processes included in three different following methods. If I disable these methods with // the popup window appears just fine, but if I enable the methods, the processes run fine, but the popup window does not appear. Any ideas/solutions ? greetings
Your window do not show until Process method is not return because main application loop implemented in main function
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog w; // or other window
w.show();
return a.exec(); // main app loop (all drawing procedures called from here
}
So if you call your PROCESSES START nothing happened until Process method returns in QApplication::exec()
You can start your processes in separate thread and send progress notification to you dialog by implementing signals\slots in queued mode
The dialog cannot be shown until your code execution exits ProcessMethod(). If you are using the QProcesses synchronously (by calling any of the waitForXXX methods), then this would cause the problem you are seeing. Anything else that holds up the main thread would also cause this problem.