启动事件循环
弄个 application,然后让他 exec() 即可。application 有三种(按继承关系排列):
- QCoreApplication:无界面,单纯开启事件循环就用它,依赖 Qt::Core
- QGUIApplication:比 QCoreApplication 多了界面,额外依赖 Qt::Gui
- QApplicatioin:比 QGuiApplication 多做了 QWidget 的初始化和关闭操作,又额外依赖 Qt::Widgets
对于 QML 程序,如果无需用到 C++ 那套 QWidget,直接用 QGUIApplication,这样就可以不用把 QtWidgets.dll 搞进来,减少体积。此时,cmake 可以这样写:
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick)
QML 窗体创建
QmlEngine+QQmlComponent+QQuickWindow
一般来说,要呈现一个窗体,需要走三步:
- QML 语法需要 QmlEngine 来解析执行
- 使用 QQmlComponent 创建单个 qml 文件对象
- 将第二步的对象放入 QQuickWindow ```cpp // 方法一
QQmlEngine engine; // QML 语法需要 QmlEngine 来解析执行
//使用 QQmlComponent 创建单个 qml 文件对象
QQmlComponent component(&engine, “qrc:/main.qml”);
QObject obj = component.create(engine.rootContext());
QQuickItem item = static_cast
QQuickWindow win; item->setParentItem(win.contentItem()); // 将第二步的对象放入 QQuickWindow win.show();
<a name="QQuickView"></a>
#### QQuickView
上面的方法有点复杂,QQuickView 把 QQmlEngine、QQmlComponent、QQuickWindow 三者结合在一起:
```cpp
// 方法二
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
view.show();
QQmlEngine *engine = view.engine();
QQuickItem *component = view.rootObject();
QQuickWindow *win = component->window();
由 component->window() 可以看出,QQuickView 是把 Component 加了 Window 的外框,
而方法一是把 Component 塞进一个 Window 里面。
QQmlApplicationEngine
QQuickView 有一个不好的地方是:自动创建了一个 Window 窗体。
QQmlApplicationEngine 是 QQmlEngine 和 QQmlComponent 结合体,不会自动创建 Window 窗体。
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
当然,要呈现一个窗体,main.qml 的 rootObject 应该是一个窗体,并且 visible 设为 true;
或者像方法一那样,新建一个 QQuickWindow,把 rootObject 塞进这个 Window。
QQmlEngine、QQmlComponent、QQmlContext 关系
qml 引擎在上下文创建组件实例。
上下文暴露数据给 qml 引擎创建的组件实例。
QML 引擎约定,加载的第一个 QML 文件为 ContextObject,而它的属性也就成了 ContextProperty。
而 QML 的全局变量本质就是 ContextProperty 。
QWidget、QWindow
QML 雄心勃勃,一心想干掉 QWidget,但是 QMainWindow 这些窗体怎么办,QPushButton 小部件怎么办?
QML 的世界中,都有替代方案:
- QWindow 用来替代 QWidget,像 QQuickWindow、QQuickView 都是 QWindow 的子类。
- Qt Quick Controls 提供了一堆控件,用来替代 QPushButton、QLabel 这些小部件。
这样,发布程序时,就可以不用把 Qt5Widgets.dll 搞进来了。
当然,想要用 QML , Qt5Quick.dll 是必须的。
参考文献:
https://stackoverflow.com/questions/17860604/what-is-the-difference-between-a-qwindow-and-qwidget