前面的文章《启动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更新,更强大。