對於Python3和QML通訊,實際上就是 PyQt5+QML+Python3混合編程,這是必須的,由於QML作圖形界面比較容易,可是作功能實現就用Python比較好,雖然QML也能嵌入 JavaScript代碼進行實現,可是這樣話還不如用Python來實現,代碼簡潔、易懂。 html
對於如下的例子,參考了以下的鏈接: 編程
Connecting QML signals in PySide: app
http://qt-project.org/wiki/Connecting_QML_Signals_in_PySide ide
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 ui
(1)QML顯式的調用Python函數 spa
定義一個類,並繼承QtCore.QObject對象,並使用@修飾符修飾pyqtSlot .net
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)
|
以下是一個完整的例子: orm
這個例子運行後,若是點擊鼠標的話,會在控制檯打印字符串。
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
}
}
}
|
運行結果以下:
本人水平有限,若是有疏漏之處,歡迎指點。