无法将Python函数绑定到QML按钮,运行报错求排查
Qt Quick前后端绑定报错:TypeError: Property 'greet' of object QVariant(PySide::PyObjectWrapper, ...) is not a function
问题场景
我在尝试绑定Qt Quick应用前后端时遇到问题,以下是我的示例代码,其中greet函数无参数,仅输出‘Hello from backend’。
原代码
main.py
from pathlib import Path from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine, QmlElement from PyQt6.QtCore import QObject, pyqtSignal, pyqtSlot import sys # 原代码遗漏sys导入,此处补充 class Calculator(QObject): def __init__(self): QObject.__init__(self) @pyqtSlot() def greet(self): print("Hello from backend") if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() backend = Calculator() engine.rootContext().setContextProperty("backend", backend) engine.load("main.qml") engine.quit.connect(app.quit) sys.exit(app.exec_())
main.qml
import QtCore import QtQuick import QtQuick.Controls import QtQuick.Dialogs ApplicationWindow { id: mainWindow width: 640 height: 480 visible: true // 补充窗口显示必要属性 Button { objectName: "checkButton" id: modelCheck text: qsTr("Check model") onClicked: backend.greet() } Connections { target: backend function onSignalPrintTxt(boolValue) { return } } }
运行报错
TypeError: Property 'greet' of object QVariant(PySide::PyObjectWrapper, 0x1006571f0) is not a function
错误原因及修正
核心问题:混用PySide6和PyQt6模块
你同时导入了PySide6的GUI/QML模块,又导入了PyQt6的核心模块(QObject、pyqtSlot等),这两个是独立的Qt Python绑定库,不能混合使用,否则会导致槽函数无法被QML正确识别。
修正方案
统一使用PySide6的模块,并替换PyQt6的装饰器为PySide6对应的版本:
修正后的main.py
from PySide6.QtGui import QGuiApplication from PySide6.QtQml import QQmlApplicationEngine from PySide6.QtCore import QObject, Slot # 使用PySide6的Slot装饰器 import sys from pathlib import Path class Calculator(QObject): def __init__(self): super().__init__() # 更简洁的父类初始化方式 @Slot() # 替换为PySide6的Slot装饰器 def greet(self): print("Hello from backend") if __name__ == "__main__": app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() backend = Calculator() engine.rootContext().setContextProperty("backend", backend) # 用绝对路径加载qml,避免工作目录导致的路径问题 qml_file = Path(__file__).parent / "main.qml" engine.load(qml_file.resolve()) if not engine.rootObjects(): sys.exit(-1) engine.quit.connect(app.quit) sys.exit(app.exec_())
额外说明
- 补充了原代码遗漏的
sys模块导入; - 使用
super().__init__()替代QObject.__init__(self),符合Python编码规范; - 改用绝对路径加载QML文件,避免因运行环境工作目录不同导致的文件找不到问题;
- 增加
engine.rootObjects()检查,方便快速排查QML加载失败情况。
内容的提问来源于stack exchange,提问作者Philipp
相关产品推荐
相关产品推荐

