In Qt main function, how does QApplication learn about Mainwindow? - c++

Looking at a simplest Qt Widget sample application that you can find from almost every Qt tutorial:
#include "notepad.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Notepad w;
w.show();
return a.exec();
}
There is one thing puzzles me. There are two major variables a and w here. a.exec() starts Qt's main loop, which suppose to interact with the main GUI component w. However, both of them live on stack and I don't see any code pass w somehow to a. So how does a be aware of the existence of w?
Does the constructor of w initializes a static data structure that a can access to check the top-level widgets?

Qt preprocess your code and build the real c++ code before compiling, its at this moment QApplication wrap all Q object in the main.cpp file and build the rest of the code from it.

Related

"Must construct a QApplication before a QWidget" error, but only on Windows builds?

I am working on a CMAKE C++ project which uses the QT Libraries. (For me, 5.15.3, for others 5.12.x)
In this project, there is a class Vtk3DViewer : public QWidget. In its constructor, it tries to create one of its member variables, which is of type QVTKOpenGLNativeWidget. This is from the VTK libraries. (Located in include\vtk-9.2\QVTKOpenGLNativeWidget.h)
For me, this new QVTKOpenGLNativeWidget() call within the constructor of my QWidget fails with the following error:
"Must construct a QApplication before a QWidget"
But that's just it, we do create a QApplication in main() well before this point. And this only happens on Windows. Linux builds appear to not have any issue.
Switching from Debug to RelWithDebugInfo moves the error - making it happen much earlier and on creating a QToolBarExt instead.
Why is this happening, and how do I fix it?
Here is an example of main():
int main(int argc, char* argv[])
{
// Set info for settings & registry
QApplication::setOrganizationName(COMPANY_NAME);
QApplication::setOrganizationDomain(COMPANY_DOMAIN);
QApplication::setApplicationName(APP_NAME);
// Set up for software-based backend for VTK
QApplication::setAttribute(Qt::AA_UseOpenGLES);
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/main-window/favicon.ico"));
// Instantiate singletons
TaskExecutionManager::getInstance(); // Instantiate the task manager
DataDispatcher::getInstance();
// Create main window with default size
MainWindow w;
w.show();
// Start application event loop
return a.exec();
}
Then the main window's constructor calls:
void MainWindow::initializeMainWindow(Ui::MainWindow* ui)
{
this->setDockOptions(AnimatedDocks | AllowNestedDocks | AllowTabbedDocks | GroupedDragging);
// Main toolbar
m_topToolBar = new QToolBarExt(this); // This causes a "Must construct a QApplication before a QWidget" error
}
The issue was that VTK was built in RELEASE, while our project was built in DEBUG.
(I did not see this as an issue, since we would never need to step into/debug VTK's code)
It appears this cryptic/incorrect error message will appear under these circumstances. Ensuring VTK and the project it includes are compiled the same way fixes it.

Use Qts QXmlSchemaValidator without QApplication

I need some help in Qt since I don't really undestand the way Qt libraries can be used in visual studio projects. I try to use the QXmlSchemaValidator class from QtXmlPatterns to validate an xml file against schema, but I can't instantiate a QApplication object since I don't have access to the main.cpp file. I don't want to create a Qt project, just try to use this schemaValidator class in one of a class' method.
This is how I try to load the schema:
QUrl url("http://.../schema.xsd");
QXmlSchema schema;
if (schema.load(url))
qDebug() << "schema is valid";
else
qDebug() << "schema is invalid";
I get this warning: "Please instantiate the QApplication object first".
I found a solution here: QEventLoop: Cannot be used without QApplication that says I need the main function to look like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Is there a way to load the schema and validate my xml files without a QApplication object?
Thanks in advance!
Yes, use QCoreApplication instead.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
//your code here
return a.exec();
}
Seriously, if some Qt features you like require an event loop, you just can't get away with it without one. About not having a "Qt project" (and maybe you mean you're not using qmake) but yet using Qt classes: good luck.

Qt5 QuickView cannot create window: no screens are available

I receive this error (title, below) whenever I try to run the following code:
#include <QCoreApplication>
#include <QQuickView>
int main(int argc, char *argv[]){
QCoreApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl::fromLocalFile("app.qml"));
QObject *object = (QObject*)view.rootObject();
view.show();
delete object;
return app.exec();
}
Cannot create window: no screens available
The program has unexpectedly finished.
All I can find online for that error are bug reports arising from specific conditions significantly more involved than the above.
app.qml is a file that runs fine alone, i.e. without the above C++ and in a separate project configured as a 'Qt Quick UI'. Giving it's qrc:// path, or deliberately specifying a file which does not exist has no effect.
Note the QObject* cast - this was not present in the docs, but without it:
/main.cpp:11: error: cannot initialize a variable of type 'QObject *' with an rvalue of type 'QQuickItem *'
How should this be done?
The QCoreApplication can be used with console application, not with GUI ones, i.e. you have to use a QGuiApplication object. It seems to me that you created a console application instead of a graphical one.
You can create a proper application via the Qt Quick Application, add your "app.qml" as a resource to that project and call such a file instead of the default "main.qml", provided by the project template.
If you want to quick fix your current project, just check that the .pro file is set to import GUI libraries:
QT += gui qml quick
Set your qml file as a resource:
Create a new resource file via file -> new File or Project... -> Qt -> Qt Resource File
Right click the newly created .qrc file and click add existing file to add your "app.qml" file
Finally, rewrite your main like this:
#include <QQuickView>
#include <QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv); // GUI APPLICATION!!!
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:///app.qml")));
view.show();
return a.exec();
}
However, going for the Qt Quick Application project would be the wiser choice.

Program crash after setting QApplication::style twice

#include <QApplication>
int main() {
QApplication::setStyle("windows");
QApplication::setStyle("windows");
}
This program produces Segmentation fault (core dumped). My qmake version is 4.7.2. Is this a Qt bug or my version is too old?
You must create an instance of QApplication before you set it's style. From the documentation
Ownership of the style object is transferred to QApplication, so
QApplication will delete the style object on application exit or when
a new style is set and the old style is still the parent of the
application object.
I'm assuming it's crashing because there is no QApplication to take ownership of the style. In general, creating the QApplication is one of the first things you should do.
#include <QApplication>
int main() {
QApplication a(argc, argv);
QApplication::setStyle("windows");
QApplication::setStyle("windows");
}

What is "QApplication app(argc, argv)" trying to do?

#include <QtGui/QApplication>
#include <QtDeclarative>
#include "qmlapplicationviewer.h"
int main(int argc, char **argv) {
QApplication app(argc, argv);
QmlApplicationViewer viewer;
viewer.setMainQmlFile("app/native/assets/main.qml");
viewer.showFullScreen();
return app.exec();
}
My C++ is a bit rusty. Can someone please explain to me what is "QApplication app(argc, argv)" trying to do ?
Is it trying to declare a function which takes in 2 arguments (argc and argv) and return a variable of type QApplication ?
The line
QApplication app(argc, argv);
creates a new instance of type QApplication and invokes the constructor of this class. In your example, the variable app now stores this instance. It is somewhat (semantically) a shorthand of this:
QApplication app = QApplication(argc, argv);
Here's a quote from Qt Docs:
The QApplication class manages the GUI application's control flow and
main settings.
QApplication contains the main event loop, where all events from the
window system and other sources are processed and dispatched. It also
handles the application's initialization, finalization, and provides
session management. In addition, QApplication handles most of the
system-wide and application-wide settings.
For any GUI application using Qt, there is precisely one QApplication
object, no matter whether the application has 0, 1, 2 or more windows
at any given time. For non-GUI Qt applications, use QCoreApplication
instead, as it does not depend on the QtGui library.
The QApplication object is accessible through the instance() function
that returns a pointer equivalent to the global qApp pointer.
So, the line
QApplication app(argc, argv);
creates an instance of the QApplication class.
QApplication is a Qt class that contains the main event loop.
When you write QApplication app(argc, argv);
you are creating a object app of this class, by calling its constructor with argc and argv
When int main(int argc, char **argv) is called while running the program, int argc is intialized to contain the number of arguments passed while running the program. char **argv contains an array of arguments passed to the program when executing it.
char* argv[0] will contain (point to) the name of the program, while the subsequent elements will point to the other arguments passed.
argc and argv are in turn, passed to the constructor of QApplication, so that one can pass Qt specific arguments when running your program.
For an example of such arguments try running ./yourProgramName --help in a terminal window
app() is not a function, it is a constructor call.
If you come from C# or Java or something, imagine it as
QApplication app = new QApplication( argc, argv );
Just that app would be a pointer this way, while it actually is the object itself if it is created like in your example.
In short, Qt needs a QApplication instance to run so signals&slots are processed (if you are using them) and events like painting etc are handled