IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> Qt for python 的属性系统使用,并注册python到qml使用 -> 正文阅读

[Python知识库]Qt for python 的属性系统使用,并注册python到qml使用

前言

今天被这个python类注册给qml调用给搞晕了,本来写对了代码,但是死活不生效,废了好长时间才找到原因,就是因为某个原因,导致报如下错误:

QWindowsContext: OleInitialize() failed:  "COM error 0xffffffff80010106 RPC_E_CHANGED_MODE (Unknown error 0x080010106)"

不说这个了,说下正题,如何让pyside中的python类对象在qml中调用呢? 就像之前调用C++一样灵活,答案毋庸置疑肯定是可以的,现在网上很多都不知道怎么用,其实方法是和C++如何被Qml调用一样,首先python必须是继续于QObject,这点是必须的,其次就是调用QQmlApplicationEngine方法来注册上下文,如下代码:

engine.rootContext().setContextProperty("qml_c_object", xxxxx)

demo示例

这个过程已经说了,其实最重要的还是代码,下面我贴出两种方式的代码,记住,无论哪种方式,qml想要使用python类,只能通过属性,信号,槽,这三种方式,下面我说的就是如何通过属性来识别:

第一种实现方式

第一种方式是直接通过@Property实现调用

main.py文件内容如下:

import sys

from PySide2.QtCore import QObject, Signal, Property, QUrl
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import QQmlApplicationEngine

class Backend(QObject):
    textChanged = Signal(str)

    def __init__(self, parent=None):
        QObject.__init__(self, parent)
        self.m_text = ""

    @Property(str, notify=textChanged)
    def text(self):
        return self.m_text

    @text.setter
    def setText(self, text):
        if self.m_text == text:
            return
        self.m_text = text
        self.textChanged.emit(self.m_text)   

if __name__ == '__main__':
    app = QGuiApplication(sys.argv)
    backend = Backend()

    backend.textChanged.connect(lambda text: print(text))
    engine = QQmlApplicationEngine()
    engine.rootContext().setContextProperty("backend", backend)
    engine.load(QUrl.fromLocalFile('main.qml'))
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

main.qml文件如下:

import QtQuick 2.10
import QtQuick.Controls 2.1
import QtQuick.Window 2.2

ApplicationWindow {
    title: qsTr("Test")
    width: 640
    height: 480
    visible: true
    Column{
        TextField{
            id: tf
            text: "Hello"
        }
        Button {
            text: qsTr("Click Me")
            onClicked: backend.text = tf.text
        } 
    }
}

第二种实现方式

第二种方式,直接调用Property宏方式显示注明方法名称,和在C++使用Q_PROPERTY() 一样,不过python这边需要接收一个返回值,然后qml调用识别的是返回值名称,下面看代码实现,就一目了然了!

main.py内容如下:

from typing import List
from PySide2.QtCore import Property, QObject, QUrl, Signal, Slot
from PySide2.QtGui import QGuiApplication
from PySide2.QtQml import qmlRegisterType
from PySide2.QtQuick import QQuickView


class Role(QObject):
    idChanged = Signal()
    nameChanged = Signal()

    def __init__(self, id_, name, parent=None):
        super().__init__(parent)

        self._id = id_
        self._name = name

    def get_id(self) -> int:
        return self._id

    def set_id(self, id_) -> None:
        if self._id != id_:
            self._id = id_
            self.idChanged.emit()

    def get_name(self) -> str:
        return self._name

    def set_name(self, name) -> None:
        if self._name != name:
            self._name = name
            self.nameChanged.emit()

    id_ = Property(int, fget=get_id, fset=set_id, notify=idChanged)
    name = Property(str, fget=get_name, fset=set_name, notify=nameChanged)


class MockRoleService(QObject):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.records = {
            1: Role(id_=1, name="Admin", parent=self),
            2: Role(id_=2, name="User", parent=self),
        }

    @Slot(result="QVariantList")
    def find_all(self) -> List[Role]:
        return list(self.records.values())


if __name__ == "__main__":
    import os
    import sys

    app = QGuiApplication(sys.argv)
    # qmlRegisterType(Role, "Models", 1, 0, "Role")
    view = QQuickView()
    current_dir = os.path.dirname(os.path.realpath(__file__))
    url = QUrl.fromLocalFile(os.path.join(current_dir, "Views/main.qml"))
    view.setSource(url)
    view.setResizeMode(QQuickView.SizeRootObjectToView)

    role_service = MockRoleService()
    view.rootContext().setContextProperty("roleService", role_service)

    if view.status() == QQuickView.Error:
        sys.exit(-1)

    view.show()

    sys.exit(app.exec_())

main.qml文件如下:

import QtQuick 2.12

Item{
    width: 640
    height: 480
    MouseArea {
        anchors.fill: parent
        onClicked: {
            var roles = roleService.find_all()
            console.log(roles)
            for (var i in roles) {
                var role = roles[i]
                console.log(role.id_, role.name);
            }
        }
    }
}

输出如下:

qml: [Role(0x55b5385589b0),Role(0x55b538558d40)]
qml: 1 Admin
qml: 2 User

总结

可以看到无论第一种还是第二种方式都是可以注册,第二种采用了QQuickView 方式加载,也是能识别注册的,基本python注册qml上下文使用,就是这两个demo诠释了!看不懂的可以留言评论,看到必回~

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-04-14 23:50:39  更:2022-04-14 23:55:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:43:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码