Qt - the object receiving the signal - qt

In a Qt application, if we have the following for example:
.
.
.
QApplication a(argc, argv);
.
.
.
QObject::connect(&button, SIGNAL(clicked()), &a, SLOT(quit()));
.
.
.
Here, I know button is the object that will send the signal. Thus, a is the object that will respond to the signal. In this case, a is a QApplication object. But, what does it really represent? For example, we knew that button is a button object, then what does a represent? Is it simply a window?
Thanks.

The QApplication does not represent any visual element. Instead it represents the whole "program" - which is of course something of more abstract a nature.

Citing from the Qt documentation
The QApplication class manages the GUI application's control flow and main settings.
The most important task of a QApplication instance is handling events: Whenever you move the mouse, for example, the application receives events from the OS (or window system), which the QApplication instance will dispatch and forward to your GUI. Also, when you emit a signal, QApplication's event loop will call the connected slots.
Other tasks in which QApplication is involved:
Command line parsing
Styling (choosing the right look for the widgets depending on the OS)
Session management
Translations/Internationalization

Related

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 application remains in memory after closing all windows

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.

Qt: Is there notification when event loop starts?

I have a Qt application with this kind of main()...
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWin;
... A separate, non-GUI thread is launched here
mainWin.Init();
mainWin.show();
app.exec();
}
This other thread that is created before the mainWin needs to know when it can start communicating with the mainWin. But since the mainWin uses Qt signals, slots, timers, etc, it's not truly ready to rock until the event loop is running (via exec()).
My question is: is there some signal or event that is emitted when the event loop has started?
Consider this. In mainWin.Init(), you can create something like a QTimer and even call .start() to kick it off. But it won't actually be run and trigger events until exec() has been called. This is why I need to know when the event loop has truly started.
You can send a signal to your window before the exec() call. This will place an entry in app's signal queue.
When exec() is running, the signal will be delivered and your window will know that the event loop is running.
A simple way would be to use QTimer::singleShot(0, &mainWin, SLOT(onEventLoopStarted())); which connects to a custom slot of your window class.
Since emitted signals don't get lost when the event loop is not yet running, your thread may not necessarily need to know when your window is ready.
Your thread could start sending signals to the window right away but it will only receive signals from the window when the event loop is running.
You can do it in the following order:
QApplication app(argc, argv);
Mainwinwdow mainWin;
QThread yourThread;
//connect the signals from the thread to the mainWin here
mainWin.Init();
mainWin.show();
yourThread.start();
return app.exec();

Correct way to quit a Qt program?

How should I quit a Qt Program, e.g when loading a data file, and discovered file corruption, and user need to quit this app or re-initiate data file?
Should I:
call exit(EXIT_FAILURE)
call QApplication::quit()
call QCoreApplication::quit()
And difference between (2) and (3)?
QApplication is derived from QCoreApplication and thereby inherits quit() which is a public slot of QCoreApplication, so there is no difference between QApplication::quit() and QCoreApplication::quit().
As we can read in the documentation of QCoreApplication::quit() it "tells the application to exit with return code 0 (success).". If you want to exit because you discovered file corruption then you may not want to exit with return code zero which means success, so you should call QCoreApplication::exit() because you can provide a non-zero returnCode which, by convention, indicates an error.
It is important to note that "if the event loop is not running, this function (QCoreApplication::exit()) does nothing", so in that case you should call exit(EXIT_FAILURE).
You can call qApp->exit();. I always use that and never had a problem with it.
If you application is a command line application, you might indeed want to return an exit code. It's completely up to you what the code is.
While searching this very question I discovered this example in the documentation.
QPushButton *quitButton = new QPushButton("Quit");
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection);
Mutatis mutandis for your particular action of course.
Along with this note.
It's good practice to always connect signals to this slot using a
QueuedConnection. If a signal connected (non-queued) to this slot is
emitted before control enters the main event loop (such as before "int
main" calls exec()), the slot has no effect and the application never
exits. Using a queued connection ensures that the slot will not be
invoked until after control enters the main event loop.
It's common to connect the QGuiApplication::lastWindowClosed() signal
to quit()
If you're using Qt Jambi, this should work:
QApplication.closeAllWindows();
if you need to close your application from main() you can use this code
int main(int argc, char *argv[]){
QApplication app(argc, argv);
...
if(!QSslSocket::supportsSsl()) return app.exit(0);
...
return app.exec();
}
The program will terminated if OpenSSL is not installed
//How to Run App
bool ok = QProcess::startDetached("C:\\TTEC\\CozxyLogger\\CozxyLogger.exe");
qDebug() << "Run = " << ok;
//How to Kill App
system("taskkill /im CozxyLogger.exe /f");
qDebug() << "Close";
example

Ways to create a QDialog outside the main thread

I am trying to create a client application in QT which requires both threads for processing and a variable amount of window instances. But I am having a hard time trying to figure out how to create a new window inside one of the processing thread. I understand that all ui elements must be created in the same thread as the QApplication class, but I need to be able to instantiate, or at least have a reference to a QDialog in another thread.
Communicating between the thread and QDialog can be done using signals, I am not worried about this, but actually creating the window is another matter. I could use signals to tell the main thread to create an instance to the window, and then retrieve the pointer to it somehow, but to me that seems a bit to complicated and ugly. Is there a better way to accomplish such a task? To create a QDialog outside the main thread were the QApplication class exists?
Edit : I have tried the Q_INVOKABLE method but it does not work across threads. I have created a view factory class which can create a QDialog of a type I specify and returns a pointer to it. This class has been instantiated in the main GUI thread and a reference to this class is sent to any worker threads. The problem is that, when a thread invokes the create method from the factory using Qt::BlockingQueuedConnection, the invoke method fails. If I change it to Qt::DirectConnection, the invoke method calls the right create method but in the current thread as the worker thread.
My main function looks like this :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
ViewFactory vFactory;
vFactory.registerCreator(Util::W_CONNECT, new ConnectWindow::ConnectCreator());
ClientApp app;
if(!app.Initialize(&vFactory))
return 0;
app.start();
a.exec();
.............................
}
And my run function from the ClientApp thread looks something like this :
void ClientApp::run()
{
QDialog * tmp = NULL;
QMetaObject::invokeMethod(this->_vFactory, "create", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QDialog*, tmp), Q_ARG(int, 0));
}
Like I said, the invokeMothod will not fail if I change the connection type to Qt::DirectConnection, so the params are not the problem, but rather calling the method across a separate worker thread.
You can only do Gui stuff in the gui thread. The obvious solution is for the worker thread to send a message to the gui thread = a signal in Qt terms.
If a worker thread needs to ask a question it should send a message to the gui thread and then block until it gets a signal back.
AFAIK, signals (or just a dynamically callable method, using Q_INVOKABLE) or an event is the way to go.
Note that, using QMetaObject::invokeMethod() (with Qt::BlockedConnection), you can call a function safely across threads and get a return value back without too much coding.
It seems like QObject::moveToThread can solve this problem. This function moves event processing loop to another thread.
Example from Qt documentation:
myObject->moveToThread(QApplication::instance()->thread());

Resources