QQuickView、QQmlApplicationEngine的区别和用法细节

前面的文章《启动QML(Qt quick app)的两种方法(包含python和QT)》,主要是讲QQuickView、QQmlApplicationEngine的不同启动方法。最近我通过不断的实践和研究,又发现一些细节,于是写下这篇文章。

1.界面如果是纯qml的,就用qquickview或者qqmlapplicationengine来启动界面。

2.QQuickView是一个便利类,可以方便的从一个qml文件创建视图。

3.QQmlApplicationEngine只能用于qml相关的应用,本身不会创建任何可视化元素,需要手工往qml文件添加。如果你使用Qt Quick里面的视觉item,你需要把qml里面加一个Window,然后将其放进去。

因为我主要是用Python和QML混合编程,就只放Python和Qml的代码,C++的代码就不放了。下面展开来讲。

1、QQmlApplicationEngine的使用

Python用QQmlApplicationEngine来调用界面:代码如下

from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import qmlRegisterType, QQmlApplicationEngine

if __name__ == "__main__":
    app = QGuiApplication(sys.argv)
    engine = QQmlApplicationEngine()
    engine.load(os.path.join(os.path.dirname(__file__), "main.qml"))
    #engine.load(QUrl(QStringLiteral("qrc:/main.qml")));  这样也可以

    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

QML界面代码如下:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
  
  ApplicationWindow {
        title: qsTr("Hello World")
        width: 640
        height: 480
        visible: true
        menuBar: MenuBar {
            Menu {
                title: qsTr("&File")
                MenuItem {
                    text: qsTr("&Open")
                    onTriggered: messageDialog.show(qsTr("Open action triggered"));
                }
                MenuItem {
                    text: qsTr("E&xit")
                    onTriggered: Qt.quit();
                }
            }
        }
        MainForm {
            anchors.fill: parent
            button1.onClicked: messageDialog.show(qsTr("Button 1 pressed"))
            button2.onClicked: messageDialog.show(qsTr("Button 2 pressed"))
            button3.onClicked: messageDialog.show(qsTr("Button 3 pressed"))
        }
        MessageDialog {
            id: messageDialog
            title: qsTr("May I have your attention, please?")
            function show(caption) {
                messageDialog.text = caption;
                messageDialog.open();
            }
        }
    }

注意细节:必须按下面的来设置,否则会调用失败,不显示窗体

      1.用QQmlApplicationEngine来调用,而被调用的Qml必须是ApplicationWindow 或者Window,也就是qml的根控件

      2. visible: true  必须把visible设置True

2、QQuickView的使用

from PySide2.QtCore import QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import qmlRegisterType, QQmlApplicationEngine
from PySide2.QtQuick import QQuickView

if __name__ == "__main__":
     app = QGuiApplication(sys.argv)
     view = QQuickView()
     view.setResizeMode(QQuickView.SizeRootObjectToView)
     view.engine().quit.connect(app.quit)

     view.setSource(QUrl('main.qml'))
     view.show()
     sys.exit(app.exec_())

qml的文件如下:

import QtQuick 2.3
import QtQuick.Controls 1.4
//实现对鼠标事件的处理和对文本的移动处理(键盘事件)

Rectangle {
    id: page
    visible: true
    width: 500; height: 500
    color: "lightgray"

}

注意细节:

1.使用QQuickView来启动,而qml的根控件就可以是  Rectangle或者Item,就不能是 ApplicationWindow 或者Window,因为QQuickView相当于可以自己创建窗体

2.用QQuickView来启动,除了不能使用ApplicationWindow/Window,并且使用stackView也会出现 root = view.rootObject()返回值是None的结果

因为我想用下面的方法来通过Python来调用qml中的函数,例如调用updateRotater函数

# -*- coding: GBK -*-
 
from PyQt5.QtCore import QUrl, QTimer
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
 
if __name__ == '__main__':
    path = 'test.qml'   # 加载的QML文件
 
    app = QGuiApplication([])
    view = QQuickView()
    view.engine().quit.connect(app.quit)
    view.setSource(QUrl(path))
    view.show()
 
    timer = QTimer()
    timer.start(2000)
    root = view.rootObject()
    timer.timeout.connect(root.updateRotater)
 
    app.exec_()
import QtQuick 2.0
 
Rectangle {
    id: page
    width: 500; height: 200
    color: "lightgray"
 
    function updateRotater() {
        rotater.angle += 45
    }
 
    Rectangle {
        id: rotater
        property real angle : 0
        x: 240; y: 95
        width: 100; height: 5
        color: "black"
 
        transform: Rotation {
            origin.x: 10; origin.y: 5
            angle: rotater.angle
        }
    }
}

正常可以运行,但是当我在qml中加入stackView后, root = view.rootObject()返回值是None

下面说说这两者之间的区别:

1.与QQuickView不同,QQmlApplicationEngine不会自动创建根窗口。 如果您使用Qt Quick中的可视项目,则需要将它们放在窗口内。

QQmlApplicationEngine向QML公开了一些中央应用程序功能,QQuickView应用程序通常会从C ++控制它:

  • 将Qt.quit()连接到QCoreApplication :: quit()
  • 从与主QML文件相邻的i18n目录自动加载转换文件。
  • 如果场景包含QQuickWindow,则自动设置孵化控制器。
  • 自动将QQmlFileSelector设置为url拦截器,将文件选择器应用于所有QML文件和资产。

在引入QQmlApplicationEngine时,

在Qt 5.0中,我们通常通过在C ++中声明一个QQuickView并在其上设置基本URL来创建Qt Quick应用程序。 这种方法的缺点是你必须使用C ++来设置宽度,高度等属性。在Qt 5.1中,我们鼓励使用Window或ApplicationWindow作为应用程序的根项,完全控制Qt Quick,所以我们现在介绍QQmlApplicationEngine使这个用例更简单一些。 QmlApplicationEngine是您设置qt快速窗口,选择正确的翻译文件以及隐式将应用程序quit()信号连接到根窗口所需的全部内容。

Qt Quick Controls 2.0能够通过新项目ApplicationWindow利用这个额外的应用程序控件,其中:

  • 类似于常规的QQuickWindow,但增加了对在QML中设置窗口特定的MenuBar,ToolBar和StatusBar的支持。
  • 可以方便地将页眉和页脚项添加到窗口中。
  • 可以从QML控制窗口的属性,外观和布局。
  • 通过其overlay属性支持弹出窗口,这可确保弹出窗口显示在其他内容之上,并且当模式弹出窗口可见时背景变暗。

因此,为了使用一些Qt Quick Controls功能,如MenuBar和Popup,我们需要:

  • 使用ApplicationWindow作为我们的顶级QML项而不是Rectangle或Item
  • 使用新的QQmlApplicationEngine从C ++而不是旧的QQuickView加载QML。总的来说: QQmlApplicationEngine比QQuickView更新,更强大。
声明:本内容为作者独立观点,不代表电子星球立场。未经允许不得转载。授权事宜与稿件投诉,请联系:editor@netbroad.com
觉得内容不错的朋友,别忘了一键三连哦!
赞 3
收藏 2
关注 17
成为作者 赚取收益
全部留言
0/200
成为第一个和作者交流的人吧