如何实现PyQt5与QML响应彼此发送的信号?

简介:

 

对于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, pyqtSlot from PyQt5.QtGui import QGuiApplication from PyQt5.QtQuick import QQuickView class 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.0

Rectangle {
    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, pyqtSlot
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

class 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.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) //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 QUrl
from PyQt5.QtGui import QGuiApplication
from PyQt5.QtQuick import QQuickView

def 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, QTimer
from PyQt5.QtGui import QGuiApplication
from 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, QUrl
from PyQt5.QtGui import QColor, QGuiApplication, QPainter, QPen
from PyQt5.QtQml import qmlRegisterType
from PyQt5.QtQuick import QQuickPaintedItem, QQuickView


class 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.0
import QtQuick 2.0

Item {
    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

 

本文转自罗兵博客园博客,原文链接:http://www.cnblogs.com/hhh5460/p/4237863.html ,如需转载请自行联系原作者
相关文章
|
存储 网络协议 文件存储
|
人工智能 达摩院 自然语言处理
超好用的开源模型平台,ModelScope阿里达摩院
超好用的开源模型平台,ModelScope阿里达摩院
1916 1
|
NoSQL API 调度
.NET开源的轻量化定时任务调度,支持临时的延时任务和重复循环任务(可持久化) - FreeScheduler
.NET开源的轻量化定时任务调度,支持临时的延时任务和重复循环任务(可持久化) - FreeScheduler
604 0
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
机器学习/深度学习 人工智能 前端开发
FacePoke:开源AI实时面部编辑神器!拖拽调整表情/头部朝向,4K画质一键生成
FacePoke是一款基于AI技术的开源实时面部编辑工具,支持通过拖拽操作调整头部朝向和面部表情,适用于多种场景。
1392 0
|
存储 弹性计算 数据管理
阿里云对象存储OSS收费标准:存储、流量和请求等多个计费项详解
阿里云对象存储OSS提供多样化的计费模式,涵盖存储、流量、请求等多项费用。存储费用方面,按量付费标准型为0.09元/GB/月,包年包月则有9元40GB等多种选择。流量费用仅对公网出方向收费,价格区间从0.25至0.50元/GB不等,支持按量付费与流量包抵扣两种方式。更多详情及精准报价,欢迎访问阿里云OSS官方页面。
8135 1
|
存储 API 数据库
QML使用Sqlite数据库存储ListModel数据
本文介绍了在QML中使用Sqlite数据库存储ListModel数据的方法,包括如何创建数据库、读取数据、动态添加和删除数据,以及如何在程序启动和退出时与数据库同步数据。
574 2
|
存储 虚拟化 索引
虚拟机数据恢复-虚拟机还原快照原理和误还原快照的数据恢复方案
由一台物理服务器迁移到ESXI上的虚拟机,虚拟机迁移完成后做了一个快照,该ESXI上面一共运行了数十台虚拟机。某天工作人员不小心将快照进行了还原,虚拟机内的数据还原到了数年前刚迁移过来时的状态,迁移过来后的这几年更新的数据全部被删除。
虚拟机数据恢复-虚拟机还原快照原理和误还原快照的数据恢复方案
|
大数据 数据处理 计算机视觉
MATLAB的条件语句
【10月更文挑战第5天】本文详细介绍了MATLAB中的条件语句与循环结构,包括`if`、`elseif`、`else`、`switch`语句以及`for`和`while`循环。通过多个示例代码,展示了如何使用这些控制结构实现逻辑判断和重复操作。文章还讨论了条件语句与循环的结合使用、嵌套结构、性能优化建议,并提供了具体的应用场景和实例分析。最后,总结了这些控制结构的重要性,并提出了未来的学习方向。
|
Java 应用服务中间件 API
如何在Java中实现WebSocket?
如何在Java中实现WebSocket?
1693 0

热门文章

最新文章