标签:
对于Python3和QML通信,实际上就是 PyQt5+QML+Python3混合编程,这是必须的,因为QML做图形界面比较容易,但是做功能实现就用Python比较好,虽然QML也能嵌入 JavaScript代码进行实现,但是这样话还不如用Python来实现,代码简洁、易懂。
对于以下的例子,参考了如下的连接:
Connecting QML signals in PySide:
http://qt-project.org/wiki/Connecting_QML_Signals_in_PySide
PyQt 5.1.1 Reference Guide -> Support for Signals and Slots:
http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html?highlight=pyqtslot#PyQt5.QtCore.pyqtSlot
(1)QML显式的调用Python函数
定义一个类,并继承QtCore.QObject对象,并使用@修饰符修饰pyqtSlot
1
2
3
4
5
6
7
8
9
|
class MyClass(QObject):
@pyqtSlot(str) # 传递参数类型字符串
def outputString(self, string):
"""
功能: 创建一个槽
参数: 输出的数据string
返回值: 无
"""
print(string)
|
创建rootContext对象,并使用setContextProperty(string, object)注册对象,这样在QML中就可以调用这个函数了。
1
2
|
context = view.rootContext()
context.setContextProperty("con", con)
|
如下是一个完整的例子:
这个例子运行后,如果点击鼠标的话,会在控制台打印字符串。
Python3代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# -*- coding: GBK -*-
from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
class MyClass(QObject):
@pyqtSlot(str) # 输入参数为str类型
def outputString(self, string):
"""
功能: 创建一个槽
参数: 输出的数据string
返回值: 无
"""
print(string)
if __name__ == ‘__main__‘:
path = ‘test.qml‘ # 加载的QML文件
app = QGuiApplication([])
view = QQuickView()
con = MyClass()
context = view.rootContext()
context.setContextProperty("con", con)
view.engine().quit.connect(app.quit)
view.setSource(QUrl(path))
view.show()
app.exec_()
|
QML代码(文件名保存为test.qml):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import QtQuick 2.0
Rectangle {
width: 320; height: 240
color: "lightgray"
Text {
id: txt
text: "Clicked me"
font.pixelSize: 20
anchors.centerIn: parent
}
MouseArea {
id: mouse_area
anchors.fill: parent // 有效区域
onClicked: {
con.outputString("Hello, Python3")
}
}
}
|
运行结果如下:
(2)QML调用Python函数,并返回
这个例子跟上一个相类似,只是这次调用Python的函数具有返回值功能。
以下是一个完整的例子:
运行程序后,点击鼠标,左上角会显示数字30。
Python3代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# -*- coding: GBK -*-
from PyQt5.QtCore import QUrl, QObject, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
class MyClass(QObject):
@pyqtSlot(int, result=str) # 声明为槽,输入参数为int类型,返回值为str类型
def returnValue(self, value):
"""
功能: 创建一个槽
参数: 整数value
返回值: 字符串
"""
return str(value+10)
if __name__ == ‘__main__‘:
path = ‘test.qml‘ # 加载的QML文件
app = QGuiApplication([])
view = QQuickView()
con = MyClass()
context = view.rootContext()
context.setContextProperty("con", con)
view.engine().quit.connect(app.quit)
view.setSource(QUrl(path))
view.show()
app.exec_()
|
QML代码(文件名保存为test.qml):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import QtQuick 2.0
Rectangle {
id: root
width: 320; height: 240
color: "lightgray"
Text {
id: txt
text: "Clicked me"
font.pixelSize: 20
anchors.centerIn: parent
}
Text {
id: txt1
text: "..."
font.pixelSize: 20
}
MouseArea {
id: mouse_area
anchors.fill: parent // 有效区域
onClicked: {
console.log("test...") // 控制台打印信息
txt1.text = con.returnValue(20)
}
}
}
|
运行效果如下:
未点击鼠标时: 点击鼠标之后:
(3)QML连接信号到Python
当QML触发事件的时候,发射一个信号给Python,此时Python调用一个函数。
先在QML中定义一个信号,
1
|
signal sendClicked(string str) // 定义信号
|
然后在捕获事件的时候,发射信号,
1
2
3
4
5
6
7
|
MouseArea {
id: mouse_area
anchors.fill: parent // 有效区域
onClicked: {
root.sendClicked("Hello, Python3") # 发射信号到Python
}
}
|
最后Python中创建一个rootObject对象,然后连接这个对象,
1
2
3
4
5
6
7
|
def outputString(string):
"""
功能: 输出字符串
参数: 输出的数据string
返回值: 无
"""
print(string)
|
1
2
|
context = view.rootObject()
context.sendClicked.connect(outputString) # 连接QML信号sendCLicked
|
以下是一个完整的例子:
这个例子中,当点击鼠标的时候,控制台会打印信息。
Python3代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
# -*- coding: GBK -*-
from PyQt5.QtCore import QUrl, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView
def outputString(string):
"""
功能: 输出字符串
参数: 输出的数据string
返回值: 无
"""
print(string)
if __name__ == ‘__main__‘:
path = ‘test.qml‘ # 加载的QML文件
app = QGuiApplication([])
view = QQuickView()
view.engine().quit.connect(app.quit)
view.setSource(QUrl(path))
view.show()
context = view.rootObject()
context.sendClicked.connect(outputString) # 连接QML信号sendCLicked
app.exec_()
|
QML代码(文件名保存为test.qml):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
import QtQuick 2.0
Rectangle {
id: root
width: 320; height: 240
color: "lightgray"
signal sendClicked(string str) // 定义信号
Text {
id: txt
text: "Clicked me"
font.pixelSize: 20
anchors.centerIn: parent
}
MouseArea {
id: mouse_area
anchors.fill: parent // 有效区域
onClicked: {
root.sendClicked("Hello, Python3") # 发射信号到Python
}
}
}
|
运行结果如下:
(4)Python调用QML函数
QML中创建一个函数,
1
2
3
|
function updateRotater() {
rotater.angle += 45
}
|
Python中创建一个rootObject对象,并连接这个函数,
1
2
|
root = view.rootObject()
timer.timeout.connect(root.updateRotater)
|
以下是一个完整的例子:
例子中,每隔1s,指针会旋转45°。
Python3代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# -*- 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_()
|
QML代码(文件名保存为test.qml):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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
}
}
}
|
运行结果如下:
本人水平有限,如果有疏漏之处,欢迎指点。
标签:
原文地址:http://my.oschina.net/u/2306127/blog/474692