Qt application remains in memory after closing all windows - qt

I'm a beginner in using Qt and OpenCV, and I have a small problem.
My application works fine, but after closing it seems that opencv.exe (application name) is still in memory.
Here is my code:
int main(int argc, char* argv[]) {
QCoreApplication a(argc, argv);
cv::Mat img = cv::imread("img.jpg");
cv::namedWindow("Image");
cv::imshow("Image",img);
return a.exec();
}
How to kill task with closing application window?
I don't sure that I work correct with exec() function.

QCoreApplication::exec() starts an event loop.
Often times this is tied to the presence of a terminal window.
With QApplication::exec() it also starts an event loop, but it usually is tied to the presence of a QMainWindow or the last QWidget that was opened.
The easiest way right now for you to close it, is to go to Projects > Run > Run in Terminal, and check it.
You may also need to go to your .pro file and add CONFIG += console.
When you start using Qt signals and slots, the event loop will be extremely useful.
Also for any of Qt's GUIs to function properly you need the exec() event loop running.
Another way that you can kill your task when running it in Qt Creator is to go to the Application Output tab at the bottom and click the red square stop button.
Hope that helps.

You could try to call qApp->quit() in the close event of your non-qt window (I don't know OpenCV though).
qApp is equivalent to QCoreApplication::instance() if you started a non-gui application (in Qt terms of course), or a QApplication if you started a gui application.

To gracefully come out of event loop started by QCoreApplication::exec() QCoreApplication::quit () must be called.
Somehow when you are done with your OpenCV stuff it should call QCoreApplication::quit (). As it is a static slot you can connect a signal to it or call it explicitly.

Related

Can I use QApplication AND QCoreApplication?

I have a console application using QCoreApplication in Qt5. This application has different functions like "printABC" or "printSUV". The output will appear in the terminal.
Now I want to make a Gui, where I can push the buttons "printABC" or "printSUV" and the output will appear in the terminal too, so that it is 'easier' to use the application.
In Qt5, I can make a console application using QCoreApplication, which I have already done.
So my question is how can I add a QApplication which runs along the way?
In the docs, it is recommended to create a QApplication/QCoreApplication in the main function, so how can I create both?
You can easily have a single application which supports both command-line (terminal) mode and GUI mode. Just use QApplication (or QGuiApplication for QML-only app).
UPDATE 1: The commenters are correct, it would be better to instantiate QCoreApplication or Q[Gui]Application depending on which is actually needed...
Then, for example, if a user passes CLI options, you just run the function(s) and send the result to sdtout (presumably like you're doing now). Otherwise show the GUI and use the same functions but to display the data some other way (in the UI).
UPDATE 2: ... So it would be better to parse the command line first and determine which Q*Application "flavor" should be used...
If you haven't yet, you can look into QCommandLineParser to help handle the CLI options. Just keep in mind that it works exactly the same with a Q[Gui]Application as well.
UPDATE 3: ... In fact QCommandLineParser can be used before a Q*Application is created. One just needs to call parse() with a list of options from argv, instead of process() with the app instance. See code example below.
In main(), handle any CLI options first. Then to NOT launch the GUI you could simply exit(0) from main() before calling app.exec().
A basic example:
int main(int argc, char *argv[]) {
QCoreApplication *app;
QCommandLineParser clp;
clp.setApplicationDescription("My app does great things.");
clp.addOptions({{"cli", "Use CLI interface"}});
QStringList opts;
for (int i=0; i < argc; ++i)
opts << QString(argv[i]);
clp.parse(opts);
if (clp.isSet("cli"))
app = new QCoreApplication(argc, argv);
else
app = new QApplication(argc, argv);
...
return app->exec(); // or maybe just 0, or app->exit(), if no event loop is needed.
}
If you want to show the output in the console from which the application was started, then you can still simply print to stdout (or whatever you're doing now). However if you want this to work on Windows, additional steps may be required... and there are a few things to consider. This would really be the topic of a different question, I think. IMHO mixing the two (GUI in one window and output in console) could be rather awkward, and showing output in GUI makes it all nicely self-contained.

Cleanly closing a qt Gui application application programatically

Hello I've been using PyQt 4.8 on windows to create a simple gui application. The gui(main window) has one button, and one QLineEdit widget. Pressing the button simply calls a function to process the contents of the QLineEdit widget.
So far it works well. My main looks like this
class StartQt4App(QtGui.QMainWindow):
def process_stuff(self,param):
#Do stuff here
if __name__="__main__":
app=QtGui.QApplications(sys.argv)
myapplication=StartQt4App()
myapplication.show()
sys.exit(app.exec_())
Using py2exe I can create an windows executable e.g mygui_app.exe
However I want to adapt it so that it can be run from the windows command line. i.e if the user types
Run mygui_app.exe "c:\text_file.txt"
The application launches, this time without the GUI and automatically processes the parameter that was entered when the application was called.
So far this is what I have come up with
class StartQt4App(QtGui.QMainWindow):
def process_stuff(self,param):
#Do stuff here
def process_stuff_again(self,param):
#Do stuff here
return
if __name__="__main__":
if len(sys.argv)==1:
app=QtGui.QApplications(sys.argv)
myapplication=StartQt4App()
myapplication.show()
sys.exit(app.exec_())
else:
app=QtGui.QApplications(sys.argv)
myapplication=StartQt4App()
myapplication.process_stuff_again(param)
sys.exit(app.exec_())
Essentially if the application has been called with parameters I don't want/need to show the gui, simply call the processing function. Once processing is done exit cleanly
Currently it works, at least as far as processing the file goes. However it does not exit, once the processing is complete. Instead the program remains active (I can see it using the Windows Task Manager).
My question is how do I programatically quit the application? so that once done it cleanly shuts itself down.
I have experimented with
app.quit()
app.exit()
myapplication.exit()
myapplication.quit()
None work, essentially the application is still alive and kicking. In desperation I removed the
sys.exit(app.exec_())
from the else portion of the code and now it just crashes, as it it processes the file and then promptly crashes. Very consistently crashes.
Any suggestion as to how to cleanly get the application to close nicely when its called from the command line?
Not really familiar with PyQt, probably you're doing something wrong in your processing function which leads your app crashed.
Also, in case you processing something synchronously, your
app.quit()
called before
app.exec_()
and doesn't have any effect because event loop (that started with app.exec_()) not started yet.
If you still need to have event loop started before your processing function called (i.e. you're using event loop in your processing function), you can do a quirk like this (it's C++, I'm not familiar with PyQt):
#include <QCoreApplication>
#include <QTimer>
#include <QDebug>
class MyApp : public QObject
{
Q_OBJECT
public slots:
void process()
{
qDebug() << "Processing...";
qDebug() << "Quit application...";
qApp->quit();;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyApp myapp;
QTimer::singleShot(0, &myapp, SLOT(process()));
int rc = a.exec();
qDebug() << "app finished with" << rc << "code";
}
#include "main.moc"
Also, QMainWindow class doesn't have quit/exit methods (at least in C++).
If you don't need to show the GUI, do you even need to run the QApplication event loop at all? You could just make process_stuff_again a staticmethod
class StartQt4App(...):
#staticmethod
def process_stuff_again(param):
...
app = QtGui.QApplication(sys.argv)
StartQt4App.process_stuff_again(param)
If you're not using any of the Qt classes in process_stuff_again, you don't even need to create the QApplication.
Or if you really need to create an instance of the main window and you absolutely need the event loop, just make sure to call .close on the window at the end of the method. By default, the QApplication should exit when no windows are left open.
def process_stuff_again(self, param):
...
self.close()

Convert a Qt GUI-based application into a console or batch application

I have a Qt GUI-based full application but now I need to use this application in a sort of pipeline in batch mode (console). I've tried several approaches but none of them worked as expected. Here is what I have now:
QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();
Here is what I need:
QApplication a(argc, argv);
QString project_path = argv[1];
MyMainWindow *w = new MyMainWindow();
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
w->loadPrjFile(project_path);
w->analyze();
w->exportResults();
a.exec();
So, basically what I need is to allow the application to get the project_path through command line (not file dialogs) and execute the methods that a user would usually follow using the GUI. The problem is that these methods should block, in the sense that one should wait for the previous one to finish.
The application itself should block, in the sense that, when executed in the shell, it should wait for the whole execution to finish before quitting. As it should work as a console application the interface should also be hidden.
If you know a way to do that, I would really appreciate a code sample of how this can be done.
The problem you have is that you're trying to develop a console app, but still using Gui widgets, such as QMainWindow. You need to start by separating the Gui classes from everything else in your main project.
I recommend you create a class, derived from QObject, which handles the processing of what you need; loadPrjFile, analyze and exportResults.
Then use an instance of this new class in your MainWindow for the GUI project and use it directly for the console project.
class Worker : public QObject
{
Q_OBJECT
public:
void loadPrjFile(const QString& path);
void analyze();
void exportResults();
};
class MyMainWindow : QMainWindow
{
private:
Worker m_pWorkerObject;
};
If you're developing a console project that doesn't need a Gui, you can use QCoreApplication, instead of QApplication.
Be aware that calling app.exec() starts Qt processing messages, so you only need that if you need a message loop to process events, which may not be the case for a console application, depending on what your app does.
This answer shows the solution that I came up with after a while. I'll put it here because it can be useful to others. The code looks like this:
QApplication a(argc, argv);
QString project_file = argv[1];
MyMainWindow *w = new MyMainWindow();
w->setVisible(false);
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
w->setBatchMode(true);
QObject::connect(w,SIGNAL(loadingFinished()),w,SLOT(analyze()));
QObject::connect(w,SIGNAL(analysisFinished()),w,SLOT(exportResults()));
QObject::connect(w,SIGNAL(exportingFinished()),w,SLOT(close()));
w->loadPrjFile(project_file);
a.exec();
The main considerations are:
w->setVisible(false) was used to hide the MainWindow as also pointed out by #Dissident penguin.
w->setBatchMode(true) was used to set a class variable that is used to supress all the other dialogs throughout the code as also pointed out by #Dissident penguin. Inside the functions I just wrapped the dialog code with an if statement like:
if (!_batchMode) { //show dialog }
Meeting the requirement of sequencial execution was not that easy. I had to create two signals: loadingFinished(), analysisFinished() and exportingFinished(). Then I emit them in the end of loadPrjFile(), analyze() and exportResults() functions respectively. This way I garantee that they are executed in order and that one waits for the other. This is needed because slots are executed asynchronously in Qt.
Finally, I could not take out the method a.exec() because if I do that the program doesn't run properly. I think this is because I'm still using the GUI, it's just hidden. This way, a.exec() is still needed.
To read arguments from the command line in an app with a GUI, you can use the global pointer qApp anywhere in your code. This is particularly useful if you want, for example, to be able to associate your GUI application with a file type, since the file name will be pipleined by the OS to your app (at least it works in Windows).
You can see a detailed answer I gave to the same question in this thread, together with the links to the appropriate documentation, which for some reason is not in the latest versions of Qt.
The second part is not that easy.
You can use w->setVisible(false) before calling a.exec(); to hide your main window, but you will have, to the best of my knowledge, to modify every method that has a dialogue to either react to the command line argument if detected, and disable the dialogue, or use the normal dialogues if no related arguments are detected.
If you only need to call methods of the main window that have no interaction with the user, then it won't be that much work, and you might get away with not calling a.exec (if and only if no part of your code is using signals and slots in batch mode), which in reality starts the main loop of the GUI and won't be needed in that case.
Something like this might work:
QApplication a(argc, argv);
MyMainWindow *w = new MyMainWindow();
if(1 < qApp->arguments().count()) //Command line arguments detected
{
QString project_path = qApp->arguments().at(1);
w->loadPrjFile(project_path);
w->analyze();
w->exportResults();
}
else //No command line arguments detected
{
a.connect(&a, SIGNAL(lastWindowClosed()), &a, SLOT(quit()));
a.exec();
}
If, on the other hand, the functions loadPrjFile(), analyze(); and exportResults() are slots and not, as your code suggests, methods of your main window, they will not be called sequentially and you will have no choice but using signals and slots so each function can notify the next one that it finished its job, and therefore will have to call a.exec

QT + boost-thread not working

I'm writing a code using both Qt and boost.
I know that qt window needs to be started in the main thread, so, I'm trying to run some code in another thread using boost (not QThread).
The problem is, if I run my code without starting the qt window, it works perfectly fine, however, if I call the app.exec(), the other thread (the boost one) stops working. I don't know what is happening, any clues?
QApplication app(argc, argv);
QMainWindow window;
//creating a separated thread and starting up
boost::thread thr1( boost::bind( &X::x, &a ) );
//if we join, it works
//thr1.joing()
//but if I run the following lines, my thr1 freezes
window.show();
app.exec();
the problem was with my boost implementation. I fixed recompiling it

Qt application not exiting, staying in memory

Here is the code I am having trouble with:
QApplication a(argc, argv);
QString path = qApp->applicationDirPath();
qApp->setQuitOnLastWindowClosed(false);
a.addLibraryPath(path+"/plugins");
TryQt w;
w.show();
return a.exec();
This is how I am starting my Application. In the Application (TryQt) I am creating several other QWidgets and Qwindows. The problem arises when I close the application The QMainWindow disappears, looks like the program exits, but it remains in the memory. (I can see from Task Manager / Processes ) .
I am also catching the closeEvent in my TryQt program and closing every thing possible I opened in there. But still no use. Does any one has any idea why this is happening?
well, it's because you're calling
qApp->setQuitOnLastWindowClosed(false);
the docs say:
This property holds whether the
application implicitly quits when the
last window is closed.
The default is true.
If this property is true, the
applications quits when the last
visible primary window (i.e. window
with no parent) with the
Qt::WA_QuitOnClose attribute set is
closed. By default this attribute is
set for all widgets except for
sub-windows. Refer to Qt::WindowType
for a detailed list of Qt::Window
objects.
and you are for some reason setting it to false.
I had a similar problem (except calling qApp->setQuitOnLastWindowClosed(true); as the previous answer suggests). I suspect one of the libraries we use doesn't clean up its thread properly and an investigation is pending, but the simplest workaround was to replace return a.exec(); with:
exit(a.exec());

Resources