PyQt5与QML通信

来源:互联网 发布:51aspx源码怎么用 编辑:程序博客网 时间:2024/06/06 03:04

对于PyQt5+QML+Python3混合编程,如何实现PyQt5与QML响应彼此发送的信号,这是一个棘手的问题。

大抵有如下五种方式:

要运行下面五个例子,千万不能在eric6中运行,会报错。错误信息是:qml-test.py文件的第一个字符是无效的标识符

 

(1)QML显式的调用Python函数,无返回值

 

#文件名:qml-test.py
#文件名:test.qml
复制代码
#!/usr/bin/env python'''(1)QML显式的调用Python函数定义一个类,并继承QtCore.QObject对象,并使用@修饰符修饰pyqtSlot创建rootContext对象,并使用setContextProperty(string, object)注册对象,    这样在QML中就可以调用这个函数了。这个例子运行后,如果点击鼠标的话,会在控制台打印字符串。'''from PyQt5.QtCore import QUrl, QObject, pyqtSlotfrom PyQt5.QtGui import QGuiApplicationfrom PyQt5.QtQuick import QQuickViewclass MyClass(QObject):    @pyqtSlot(str)    # 输入参数为str类型    def outputString(self, 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_()
复制代码

 

复制代码
import QtQuick 2.0Rectangle {    width: 320; height: 240    color: "lightblue"    Text {        id: txt        text: "Clicked me"        font.pixelSize: 20        anchors.centerIn: parent    }    MouseArea {        id: mouse_area        anchors.fill: parent  // 有效区域        onClicked: {           con.outputString("Hello, Python3") //QML显式的调用Python函数           }    }}
复制代码

 

 

 

(2)QML显式的调用Python函数,有返回值

 

#文件名:qml-test2.py
#文件名:test2.qml
复制代码
#!/usr/bin/env python'''(2)QML显式的调用Python函数,并有返回这个例子跟上一个相类似,只是这次调用Python的函数具有返回值功能。运行程序后,点击鼠标,左上角会显示数字30。'''from PyQt5.QtCore import QUrl, QObject, pyqtSlotfrom PyQt5.QtGui import QGuiApplicationfrom PyQt5.QtQuick import QQuickViewclass MyClass(QObject):    @pyqtSlot(int, result=str)    # 声明为槽,输入参数为int类型,返回值为str类型    def returnValue(self, value):        return str(value+10)if __name__ == '__main__':    path = 'test2.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_()
复制代码

 

复制代码
import QtQuick 2.0Rectangle {    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) //QML显式的调用Python函数            }    }}
复制代码

 

 

 

(3)QML连接信号到Python

 

#文件名:qml-test3.py
#文件名:test3.qml
复制代码
#!/usr/bin/env python'''(3)QML连接信号到Python当QML触发事件的时候,发射一个信号给Python,此时Python调用一个函数。                先在QML中定义一个信号,然后在捕获事件的时候,发射信号,最后Python中创建一个rootObject对象,然后连接这个对象,这个例子中,当点击鼠标的时候,控制台会打印信息。'''from PyQt5.QtCore import QUrlfrom PyQt5.QtGui import QGuiApplicationfrom PyQt5.QtQuick import QQuickViewdef outputString(string):    print(string)if __name__ == '__main__':    path = 'test3.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_()
复制代码

 

复制代码
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-test4.py
#文件名:test4.qml
复制代码
# -*- coding: utf-8 -*-'''(4)Python调用QML函数QML中创建一个函数,Python中创建一个rootObject对象,并连接这个函数,例子中,每隔1s,指针会旋转45 deg;。'''from PyQt5.QtCore import QUrl, QTimerfrom PyQt5.QtGui import QGuiApplicationfrom PyQt5.QtQuick import QQuickView if __name__ == '__main__':    path = 'test4.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) # 调用QML函数                      app.exec_()
复制代码

 

复制代码
import QtQuick 2.0 Rectangle {    id: page    width: 500; height: 200    color: "lightgray"     function updateRotater() {// 定义函数                                     rotater.angle += 5    }     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        }    }}
复制代码

 

 

 (5)信号/槽 机制

 

#文件名:qml-test5.py
#文件名:test5.qml
复制代码
from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QRectF, Qt, QUrlfrom PyQt5.QtGui import QColor, QGuiApplication, QPainter, QPenfrom PyQt5.QtQml import qmlRegisterTypefrom PyQt5.QtQuick import QQuickPaintedItem, QQuickViewclass PieChart(QQuickPaintedItem):    chartCleared = pyqtSignal() # 定义信号    @pyqtProperty(str)    def name(self):        return self._name    @name.setter    def name(self, name):        self._name = name    @pyqtProperty(QColor)    def color(self):        return self._color    @color.setter    def color(self, color):        self._color = QColor(color)    def __init__(self, parent=None):        super(PieChart, self).__init__(parent)        self._name = ''        self._color = QColor()    def paint(self, painter):        painter.setPen(QPen(self._color, 2))        painter.setRenderHints(QPainter.Antialiasing, True)        rect = QRectF(0, 0, self.width(), self.height()).adjusted(1, 1, -1, -1)        painter.drawPie(rect, 90 * 16, 290 * 16)    @pyqtSlot()    def clearChart(self):        self.color = QColor(Qt.transparent)        self.update()        self.chartCleared.emit() # 发射信号if __name__ == '__main__':    import os    import sys    app = QGuiApplication(sys.argv)    qmlRegisterType(PieChart, "Charts", 1, 0, "PieChart")    view = QQuickView()    view.setResizeMode(QQuickView.SizeRootObjectToView)    view.setSource(            QUrl.fromLocalFile(                    os.path.join(os.path.dirname(__file__),'tes5.qml')))    view.show()    sys.exit(app.exec_())
复制代码

 

复制代码
import Charts 1.0import QtQuick 2.0Item {    width: 300; height: 200    PieChart {        id: aPieChart        anchors.centerIn: parent        width: 100; height: 100        color: "red"        onChartCleared: console.log("The chart has been cleared") //    }    MouseArea {        anchors.fill: parent        onClicked: aPieChart.clearChart()    }    Text {        anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }        text: "Click anywhere to clear the chart"    }}
复制代码

 

 

 

 

参考:

【QML与Python通信】

http://my.oschina.net/u/1275030/blog/186341

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

0 0
原创粉丝点击