QtQuick工程里的main函数解析
Categories:
2 分钟阅读
当然!这是对 main 函数的详细解读,涵盖了各个部分的功能和目的。
代码逐行解释
int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
QGuiApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);:设置 Qt 应用程序的属性,强制使用软件渲染 OpenGL。这在没有硬件加速的环境中(例如某些虚拟机或嵌入式系统)非常有用,确保 OpenGL 渲染功能的兼容性。
set_qt_environment();
set_qt_environment():这似乎是一个自定义函数,用于设置 Qt 环境的其他参数或配置。具体内容取决于你的实际实现。
QGuiApplication GUI_app(argc, argv);
QGuiApplication:创建 Qt 的 GUI 应用程序对象,处理与用户界面相关的任务。argc和argv用于传递命令行参数。
// 文件路径
QString iconPath = "://images/icons/app_icon.svg";
iconPath:指定应用程序图标的路径。路径使用 Qt 的资源系统(://表示 Qt 资源路径)。
// 检查文件是否存在
if (QFile::exists(iconPath)) {
// 文件存在,设置图标
glb_GUI_app.setWindowIcon(QIcon(iconPath));
// qDebug() << "Icon found and set.";
} else {
// 文件不存在,处理错误
qDebug() << "main(): Icon file not found:" << iconPath <<"currentDir="<< QDir::currentPath();
}
QFile::exists(iconPath):检查指定路径的图标文件是否存在。glb_GUI_app.setWindowIcon(QIcon(iconPath)):如果图标文件存在,则设置应用程序的窗口图标。qDebug():用于调试输出,显示图标文件的存在状态和当前工作目录。如果图标文件不存在,会输出相关错误信息。
// ********************** qml **********************************************
QQmlApplicationEngine engine;
// const QUrl url(u"qrc:/qt/qml/Main/main.qml"_qs);
const QUrl url(u"qrc:/qt/qml/content/Entry.qml"_qs);
QQmlApplicationEngine:创建 QML 引擎对象,用于加载和管理 QML 文件。url:指定要加载的 QML 文件的路径。这里加载的是Entry.qml文件。
ASCtl_Opts *class_opts = new Class_Opts();
Class_Opts:创建一个 C++ 自定义类的实例,这个对象将暴露给 QML 界面,以便在 QML 中访问和使用。QObject::connect(button, ):注释掉了的代码行,可能是用于连接某个按钮的信号和槽。
QObject::connect(
&engine,
&QQmlApplicationEngine::objectCreated,
&GUI_app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
},
Qt::QueuedConnection);
QObject::connect:连接信号和槽。这里连接的是QQmlApplicationEngine的objectCreated信号到一个 lambda 函数。objectCreated:表示 QML 对象已经创建。- lambda 函数:检查创建的对象是否为空,并且 URL 是否与预期的 URL 匹配。如果对象为空且 URL 匹配,则应用程序退出,返回错误码
-1。 Qt::QueuedConnection:信号和槽的连接类型,表示槽函数将在接收线程的事件循环中执行。
engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml");
engine.addImportPath(":/");
addImportPath:添加 QML 模块的导入路径。第一个路径是应用程序的工作目录下的qml子目录,第二个路径是 Qt 的资源系统路径。
engine.rootContext()->setContextProperty("class_Opts", class_opts);
engine.load(url);
setContextProperty:将 C++ 对象 (class_opts) 设置为 QML 上下文属性,使 QML 可以访问这个对象。engine.load(url):加载指定的 QML 文件并显示其界面。
if (engine.rootObjects().isEmpty()) {
return -1;
}
rootObjects():获取 QML 引擎中加载的根对象。如果根对象为空,说明 QML 文件加载失败,程序返回-1退出。
return glb_GUI_app.exec();
}
GUI_app.exec():启动应用程序的事件循环。这个方法会阻塞,直到应用程序退出。它处理所有的用户输入、定时器事件等。
总结
- 设置属性:设置 Qt 应用程序的属性来使用软件渲染 OpenGL。
- 设置环境:调用自定义函数来配置 Qt 环境。
- 创建应用程序对象:
QGuiApplication处理 GUI 相关任务。 - 设置图标:检查并设置应用程序窗口图标。
- 创建 QML 引擎:用于加载和管理 QML 文件。
- 创建和设置 C++ 对象:将 C++ 对象暴露给 QML。
- 连接信号和槽:确保 QML 文件正确加载。
- 设置导入路径:为 QML 引擎添加模块导入路径。
- 加载 QML 文件:实际加载并显示 QML 界面。
- 启动事件循环:进入事件循环,处理应用程序事件。
这个 main 函数展示了如何在 Qt 中设置应用程序图标、加载 QML 界面,并将 C++ 对象暴露给 QML,同时确保应用程序在启动时能够正确处理潜在的错误。
暴露整个类对象给QML的意义何在?
暴露整个 C++ 类的对象给 QML 主要有以下几个目的和考虑,但这些目的在不同的场景下可能有不同的实现方式,因此也需要根据实际需求来选择是否采用 Q_PROPERTY 或其他方式。
1. 访问复杂逻辑或功能:
- 如果你有一个复杂的 C++ 类,这个类封装了一些业务逻辑、算法或功能(例如网络请求、数据处理、硬件交互等),你可以通过暴露整个对象给 QML,让 QML 层能够调用这个对象的方法。这些方法可能不只是简单的数据访问,还包括一些逻辑操作,比如计算、状态管理等。
- 在这种情况下,QML 通过调用 C++ 对象的方法,可以利用 C++ 的强大功能,弥补 QML 本身的能力不足。例如,执行某些复杂的操作,然后将结果返回给 QML。
2. 共享和管理状态:
- 如果你的 C++ 类管理了一些全局或共享状态(例如应用程序的配置、运行状态、数据缓存等),暴露这个对象给 QML 可以让 QML 访问和操作这些状态。在这种情况下,暴露整个对象可以简化在多个 QML 组件之间共享数据或状态的需求。
3. 整合 C++ 和 QML 的开发:
- 在某些项目中,可能需要将 C++ 层的功能和 QML 层的 UI 进行紧密整合。暴露整个 C++ 类的对象可以减少接口设计的复杂性,使得 QML 可以直接利用 C++ 层的现有代码,不需要重复定义接口或桥接代码。
4. 使用单例模式的好处:
- 如果你使用单例模式暴露 C++ 对象,那么这个对象在整个应用程序中只有一个实例。这在某些情况下很有用,比如你希望确保某些数据或状态在应用程序的所有部分中保持一致。这种方式常用于全局管理器类(如设置管理器、数据库连接管理器等),这些类的实例通常只有一个,且在应用程序的整个生命周期内都存在。
5. Q_PROPERTY 的作用:
- 如果你仅仅暴露整个 C++ 对象而不使用
Q_PROPERTY,那么 QML 层可能无法直接访问对象的属性,尤其是私有或受保护的成员变量。Q_PROPERTY的作用在于允许 QML 层将某些 C++ 属性作为 QML 属性来使用,使得这些属性可以直接在 QML 中绑定、显示,并在值变化时自动触发更新。 - 另一方面,如果你不使用
Q_PROPERTY,但仍然希望 QML 能访问到某些公有数据,你可能需要手动定义 getter 和 setter 方法,然后在 QML 中通过调用这些方法来获取或设置数据。然而,这种方式无法实现自动数据同步,且代码更为冗长。
总结:
暴露整个 C++ 对象给 QML 的意义在于允许 QML 层访问和调用这个对象所提供的功能和方法,而不仅仅是访问简单的数据。如果只是为了访问某个数据属性,Q_PROPERTY 是更好的选择,它不仅可以简化代码,还能实现数据的自动同步更新。
如果你发现暴露整个类对象对于你的需求并不合适或不方便,那么你可以选择只暴露必要的功能和属性(例如通过 Q_PROPERTY),这样可以确保代码的清晰性和维护性。选择合适的方式取决于你的具体应用场景和需求。