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.
Related
I am running a small app on KDE Plasma 5 created with Qt and the KDE framework. Almost everything works like a charm, just one part doesn't work. I just cannot set the application display name. I have the following code:
int main(int argc, char **argv) {
QApplication application(argc, argv);
KLocalizedString::setApplicationDomain("blender-render-control");
KCrash::initialize();
KAboutData aboutData(QStringLiteral("blender-render-control-center"),
i18n("Blender Render Control Center"),
QStringLiteral("1.0"),
i18n("A simple application to control the blender render control server"),
KAboutLicense::Custom,
i18n("Copyright 2019, Knerd "));
aboutData.addAuthor(i18n("Knerd"), i18n("Author"), QStringLiteral("knerd#knerd.knerd"));
aboutData.setOrganizationDomain("knerd.knerd");
aboutData.setDesktopFileName(QStringLiteral("knerd.knerd.blender-render-control"));
KAboutData::setApplicationData(aboutData);
QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("knerd.knerd.blender-render-control")));
application.setApplicationDisplayName(i18n("Blender Render Control Center"));
application.setApplicationName(i18n("Blender Render Control Center"));
QCommandLineParser parser;
aboutData.setupCommandLine(&parser);
parser.process(application);
aboutData.processCommandLine(&parser);
auto *window = new MainWindow();
window->show();
return QApplication::exec();
}
From reading the docs and checking some examples, this should set the application title in my KDE environment. But it doesn't, the application name is the name of the executable.
Is this a bug in KDE or am I doing something wrong?
The docs are a bit confusing on what the applicationName and displayApplicationName are actually used for, there has been some bug reports about it, and behavior has changed between versions if I remember correcly.
If you want a window-title, I think you can do.
window->setWindowTitle( QCoreApplication::applicationName() );
I'd like to know how to pass command line arguments to an already open program. So the user runs "backup.exe -job awef" and backup.exe recognizes there is an already open process and passes the argument to the already open process so users can command the program to do what they wish from the command line or a shortcut in windows.
Thanks!
You can achieve your goal by using QtSingleApplication that handles the commandline arguments on messageReceived, as per https://doc.qt.io/archives/qtextended4.4/qtopiadesktop/qtsingleapplication.html#QtSingleApplication
At the beginning of your application, you will need to check if you can sendMessage with your commandline arguments to an already running instance, and then quit. Otherwise, you will continue starting your app, as follows
int main(int argc, char* argv[])
{
QtSingleApplication app("MySingleInstance", argc, argv);
// try to send commandline arguments
if(app.sendMessage(app.arguments().join("$")))
{
return 0;
}
/* connect your messageRecieved signal to slot
SomeClass::slotLoadCommandLine to be able to handle
the commandline arguments from sendMessage*/
QObject::connect(qApp, SIGNAL(messageReceived(QString)),
SomeClass, SLOT(slotLoadCommandLine(QString)));
//start your application
return app.exec();
}
Edit
the solution above is for Qt4, if you are using Qt5 you will need to use
SingleApplication instead
https://forum.qt.io/topic/22460/solved-qtsingleapplication-and-qt-5/5
How to use QtSingleApplication?
Another option could be using sockets (e.g. QTcpSocket). But you will need to create a another application that forwards your commandline arguments .. See this example http://www.bogotobogo.com/Qt/Qt5_QTcpSocket_Signals_Slots.php
A patched QtSingleApplication library for QT 5 is available as discussed here:
https://forum.qt.io/topic/71778/what-happened-to-qtsingleapplication
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()
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
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.