qt笔记之main.cpp加载qml文件的3种方法QQuickView 、QQmlApplicationEngine、QQuickWidget
—— 2024-06-16 下午
code review!
文章目录
- qt笔记之main.cpp加载qml文件的3种方法QQuickView 、QQmlApplicationEngine、QQuickWidget
- 1.使用qtcreator创建qml空项目,默认使用QQmlApplicationEngine
- 1.1.main.cpp
- 1.2.qml
- 1.3.qml_test.pro
- 1.4.qml.qrc
- 2.`QQuickView` 和 `QQmlApplicationEngine`对比
- 使用 `QQuickView`
- 使用 `QQmlApplicationEngine`
- 对比与选择
- 3.`QQuickView` 和 `QQmlApplicationEngine`进一步对比
- 使用 `QQuickView` 加载 QML 文件
- 使用 `QQmlApplicationEngine` 加载 QML 文件
- 结论
- 4.QQuickView 、QQmlApplicationEngine、QQuickWidget对比表格
- 总结
时序和新旧顺序
- Qt 5.0 引入 QQuickView
- Qt 5.1 引入 QQmlApplicationEngine
- Qt 5.3 引入 QQuickWidget
1.使用qtcreator创建qml空项目,默认使用QQmlApplicationEngine
创建项目后的出现的文件列表
user@user-vm:~/qt_cpp_test/qml_test$ ls
main.cpp main.qml qml.qrc qml_test.pro
1.1.main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
1.2.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
}
1.3.qml_test.pro
QT += quick
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Refer to the documentation for the
# deprecated API to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
1.4.qml.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
2.QQuickView
和 QQmlApplicationEngine
对比
在使用 Qt Creator 创建一个空的 QML 程序时,可以选择使用 QQuickView
或 QQmlApplicationEngine
来加载和显示 QML 文件。在 Qt Creator 中创建一个新的 Qt Quick 应用程序时,默认情况下并不会提供选项让选择使用 QQuickView 或 QQmlApplicationEngine。通常,创建的模板会使用 QQmlApplicationEngine,因为它是一个更通用和灵活的类,适用于大多数应用场景。
使用 QQuickView
QQuickView 是一个 QWindow 子类,用于创建一个独立窗口来显示 QML 内容。它更适用于纯 QML 应用程序或者需要单独窗口显示 QML 内容的应用。
QQuickView: 如果的应用程序主要使用 QML,或者需要一个独立窗口来显示 QML 内容,那么 QQuickView 更加适合。
- 当使用 QQuickView 时,确保没有无意中创建第二个窗口。例如,不要在 QML 文件中再创建一个 Window 或 ApplicationWindow,因为 QQuickView 本身已经是一个窗口。
- 如果在 QML 文件中使用 Window 或 ApplicationWindow,则会导致 QQuickView 运行时弹出两个窗口。因此,使用 QQuickView 时,应避免在 QML 文件中使用 Window 或 ApplicationWindow。
使用 QQmlApplicationEngine
QQmlApplicationEngine
是一个更加灵活的类,可用于加载和管理 QML 组件,并且可以结合 C++ 对象进行更复杂的逻辑处理。下面是一个使用 QQmlApplicationEngine
来加载 QML 文件的示例程序:
- 当使用 QQmlApplicationEngine 时,QML 文件应该包含一个顶层窗口组件,例如 Window 或 ApplicationWindow,才能正确显示窗口。
对比与选择
- QQuickView: 适用于需要创建一个独立窗口来显示 QML 内容的简单应用程序。它提供了一个简洁的方法来加载和显示 QML 文件。
- QQmlApplicationEngine: 提供了更灵活的功能,适用于需要加载多个 QML 文件或需要更复杂的 C++ 与 QML 交互的应用程序。
通常,对于简单的 QML 应用程序,可以使用 QQuickView
。对于复杂的项目,尤其是需要与 C++ 代码进行较多交互的项目,推荐使用 QQmlApplicationEngine
。
3.QQuickView
和 QQmlApplicationEngine
进一步对比
以下是 QQuickView
和 QQmlApplicationEngine
的对比表格,特别关注它们在加载 QML 文件时的行为,以及是否会导致弹出两个窗口的情况。
特性 | QQuickView | QQmlApplicationEngine |
---|---|---|
主要用途 | 用于显示单个 QML 文件的视图组件 | 用于管理和加载整个 QML 应用程序 |
加载 QML 文件 | view.setSource(QUrl("qrc:/main.qml")) | engine.load(QUrl("qrc:/main.qml")) |
顶层组件 | 不需要 Window 或 ApplicationWindow | 需要 Window 或 ApplicationWindow |
是否会弹出两个窗口 | 如果 QML 文件中包含 Window 或 ApplicationWindow ,则会弹出两个窗口 | 正常情况下不会弹出两个窗口,除非有多个顶层组件 |
配置窗口属性 | 通过 QQuickView 的方法直接配置 | 通过 QML 文件中的 Window 或 ApplicationWindow 配置 |
示例代码加载 QML | [见下文示例代码] | [见下文示例代码] |
适用场景 | 简单的 QML 界面显示 | 全功能的 QML 应用程序 |
使用 QQuickView
加载 QML 文件
C++ 代码:
#include <QGuiApplication>
#include <QQuickView>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.show();
return app.exec();
}
QML 文件(main.qml):
import QtQuick 2.0
Rectangle {
width: 640
height: 480
color: "lightblue"
Text {
text: "Hello, World!"
anchors.centerIn: parent
}
}
注意: 当使用
QQuickView
时,不要在 QML 文件中使用Window
或ApplicationWindow
组件,否则会弹出两个窗口。
使用 QQmlApplicationEngine
加载 QML 文件
C++ 代码:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[]) {
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
QML 文件(main.qml):
import QtQuick 2.0
import QtQuick.Window 1.0
Window {
visible: true
width: 640
height: 480
color: "lightblue"
Text {
text: "Hello, World!"
anchors.centerIn: parent
}
}
注意: 当使用
QQmlApplicationEngine
时,必须在 QML 文件中包含一个Window
或ApplicationWindow
组件,否则即使加载成功也不会弹出窗口。
结论
QQuickView
:适用于简单的单视图应用,确保 QML 文件没有Window
或ApplicationWindow
组件,以避免弹出两个窗口。QQmlApplicationEngine
:适用于更复杂的 QML 应用,需要在 QML 文件中包含Window
或ApplicationWindow
组件,确保正常显示窗口。
4.QQuickView 、QQmlApplicationEngine、QQuickWidget对比表格
特性 | QQuickView | QQmlApplicationEngine | QQuickWidget |
---|---|---|---|
类型 | QWindow 子类 | 无窗口类,管理 QML 组件 | QWidget 子类 |
使用场景 | 独立窗口显示 QML 内容 | 复杂应用,加载多个 QML 文件,C++ 与 QML 交互 | 传统 QWidget 应用中嵌入 QML 内容 |
布局支持 | 不支持 QWidget 布局管理器 | 不适用 | 支持 QWidget 布局管理器 |
OpenGL 支持 | 使用 OpenGL 渲染 | 使用 OpenGL 渲染 | 默认使用 OpenGL 渲染(可禁用) |
混合界面 | 适合纯 QML 应用或需要独立窗口的场景 | 适合复杂的 QML 应用和 C++ 交互 | 适合在现有 QWidget 应用中嵌入 QML 内容 |
加载 QML 文件 | 通过 setSource 方法 | 通过 load 方法 | 通过 setSource 方法 |
性能 | 较高性能,直接渲染到窗口 | 较高性能,直接管理 QML 组件 | 相对较低,需处理 QWidget 和 QML 之间的转换 |
错误处理 | 基本的错误处理 | 提供更详细的错误处理机制 | 基本的错误处理 |
渲染控制 | 完全控制 QML 内容的渲染 | 完全控制 QML 内容的渲染 | 需要处理 QWidget 和 QML 的渲染同步问题 |
跨平台支持 | 是 | 是 | 是 |
便捷性 | 简单易用,快速原型开发 | 灵活,适合复杂应用 | 便于在现有 QWidget 应用中集成 QML |
C++ 与 QML 交互 | 支持,但不如 QQmlApplicationEngine 灵活 | 支持更复杂和灵活的交互 | 支持,但需要处理 QWidget 和 QML 的交互问题 |
窗口管理 | 独立窗口 | 无窗口管理 | 嵌入到现有 QWidget 界面中 |
适用项目类型 | 小型到中型项目,独立的 QML 应用 | 中型到大型项目,复杂的 QML 和 C++ 应用 | 需要在现有的 QWidget 应用中嵌入 QML 的项目 |
总结
-
QQuickView:
- 适用于需要创建独立窗口来显示 QML 内容的应用。
- 提供简单的接口和较高的性能,适合纯 QML 应用或需要快速原型开发的场景。
-
QQmlApplicationEngine:
- 适用于复杂应用,尤其是需要加载多个 QML 文件和处理复杂 C++ 与 QML 交互的场景。
- 提供更详细的错误处理机制和灵活性,适合中型到大型项目。
-
QQuickWidget:
- 适用于需要在现有 QWidget 应用中嵌入 QML 内容的场景。
- 支持 QWidget 布局管理器,但在性能上可能稍逊,需要处理 QWidget 和 QML 之间的渲染同步问题。