You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySide6从Slot返回自定义模型报错:属性非函数问题求助

解决QML调用Python Slot函数提示“不是函数”的问题

我在给QML的ListView组件配置详情窗口时,通过Qt.createComponent创建新Window并传递选中项信息,尝试将嵌套ListView的model绑定到带@Slot装饰的Python函数返回值(该函数返回自定义QAbstractListModel实例),但点击打开窗口时出现以下错误:

file:///home/cassidy/Projects/portmod/portmod/_gui/Manage/PackageDetailsWindow.qml:50: TypeError: Property 'get_local_flags_model' of object Config(0x55907ace9e70) is not a function

以下是具体的排查和修复方案:

1. 确保Config类继承自QObject

Python中带有@Slot装饰器的函数所在类必须继承QtCore.QObject,否则QML无法识别其为可调用的槽函数。修改Config类定义:

from PySide6.QtCore import QObject, Slot

class Config(QObject):
    def __init__(self):
        super().__init__()
        # 其他初始化逻辑
    
    @Slot(str, result=QObject)
    def get_local_flags_model(self, atom: str) -> FlagListModel:
        return FlagListModel(get_local_flags(Atom(atom)))

2. 确认Config实例已注册到QML上下文

要让QML访问config对象,必须在Python代码中将其注入QML上下文环境:

from PySide6.QtQml import QQmlApplicationEngine

engine = QQmlApplicationEngine()
config_instance = Config()
# 将config实例注册为QML全局变量
engine.rootContext().setContextProperty("config", config_instance)
engine.load("main.qml")

若缺少这一步,QML中的config变量可能指向无效对象,导致找不到目标槽函数。

3. 验证Slot装饰器参数匹配度

确保@Slot装饰器的参数与函数签名完全一致:

  • 输入参数类型为str(与函数的atom参数类型对应)
  • result指定返回值类型为QObject(因为FlagListModel继承自QAbstractListModel,而后者是QObject的子类)

4. 修复QML模型角色引用错误

原QML代码中model.check的引用无效,因为自定义模型未定义对应角色。需补充角色定义并修正QML引用:

第一步:扩展FlagListModel的角色定义

from typing import Any, Dict, Tuple, Union
from PySide6.QtCore import QAbstractListModel, QModelIndex, Qt, QObject

class FlagListModel(QAbstractListModel):
    # 自定义角色
    CheckRole = Qt.ItemDataRole.UserRole + 1
    DescriptionRole = Qt.ItemDataRole.UserRole + 2

    def __init__(self, use_flags: Dict[str, Tuple[bool, str]]):
        super().__init__()
        self._data = use_flags
        # 角色名称映射,供QML识别
        self._roles = {
            Qt.ItemDataRole.DisplayRole: b"display",
            self.CheckRole: b"check",
            self.DescriptionRole: b"description"
        }
    
    def roleNames(self) -> Dict[int, bytes]:
        return self._roles
    
    def rowCount(self) -> int:
        return len(self._data)

    def data(
        self,
        index: Union[QModelIndex, QtCore.QPersistentModelIndex],
        role: int,
    ) -> Any:
        key = list(self._data.keys())[index.row()]
        value = self._data[key]
        if role == Qt.ItemDataRole.DisplayRole:
            return key
        elif role == self.CheckRole:
            return Qt.CheckState.Checked if value[0] else Qt.CheckState.Unchecked
        elif role == self.DescriptionRole:
            return value[1]
        return None

第二步:修正QML中的Delegate引用

delegate: CheckDelegate {
    text: model.display
    checkState: model.check
    width: ListView.view.width - 20
}

5. 延迟模型赋值(可选)

若窗口初始化时detailsWindow.atom尚未完成赋值,可能导致函数调用失败。可通过Component.onCompleted延迟绑定:

ListView {
    id: useListView
    clip: true
    width: parent.width
    height: parent.height
    Component.onCompleted: {
        model = config.get_local_flags_model(detailsWindow.atom)
    }
    ScrollBar.vertical: ScrollBar {}
}

内容的提问来源于stack exchange,提问作者PopeRigby

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:05:26