启动事件循环

弄个 application,然后让他 exec() 即可。application 有三种(按继承关系排列):

  • QCoreApplication:无界面,单纯开启事件循环就用它,依赖 Qt::Core
  • QGUIApplication:比 QCoreApplication 多了界面,额外依赖 Qt::Gui
  • QApplicatioin:比 QGuiApplication 多做了 QWidget 的初始化和关闭操作,又额外依赖 Qt::Widgets

对于 QML 程序,如果无需用到 C++ 那套 QWidget,直接用 QGUIApplication,这样就可以不用把 QtWidgets.dll 搞进来,减少体积。此时,cmake 可以这样写:

  1. find_package(Qt5 COMPONENTS Core Quick REQUIRED)
  2. 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(obj);

QQuickWindow win; item->setParentItem(win.contentItem()); // 将第二步的对象放入 QQuickWindow win.show();

  1. <a name="QQuickView"></a>
  2. #### QQuickView
  3. 上面的方法有点复杂,QQuickView 把 QQmlEngine、QQmlComponent、QQuickWindow 三者结合在一起:
  4. ```cpp
  5. // 方法二
  6. QQuickView view;
  7. view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));
  8. view.show();
  9. QQmlEngine *engine = view.engine();
  10. QQuickItem *component = view.rootObject();
  11. QQuickWindow *win = component->window();

由 component->window() 可以看出,QQuickView 是把 Component 加了 Window 的外框,
而方法一是把 Component 塞进一个 Window 里面。

QQmlApplicationEngine

QQuickView 有一个不好的地方是:自动创建了一个 Window 窗体。
QQmlApplicationEngine 是 QQmlEngine 和 QQmlComponent 结合体,不会自动创建 Window 窗体。

  1. QQmlApplicationEngine engine;
  2. 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