PyCharm提示Dialog类存在未解析的属性引用'setModel'的问题排查与解决
嗨,我来帮你分析这个问题——其实这不是代码运行的错误,而是PyCharm静态代码分析的「误报」,原因很简单:
PyCharm没办法通过静态分析识别self.findChild(QTableView, "tableView")的具体返回类型。findChild方法的返回值默认被推断为QObject类型,而QObject并没有setModel这个方法,所以PyCharm就抛出了「未解析的属性引用」的提示,但实际上你的代码运行起来是完全正常的,因为运行时self.table确实是QTableView实例。
下面给你几个实用的解决方案:
解决方案1:添加类型提示(最推荐)
直接给self.table标注明确的类型,告诉PyCharm它是QTableView实例,修改你的__init__方法即可:
from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtWidgets import QDialog, QTableView from PyQt5.uic import loadUi class Dialog(QDialog): def __init__(self): super(Dialog, self).__init__() loadUi("dialog.ui", self) # 添加类型标注,明确self.table的类型 self.table: QTableView = self.findChild(QTableView, "tableView") def fill_table(self, data): column_names = ["full_name", "mail", "age", "phone_number"] model = QStandardItemModel(1, 4) model.setHorizontalHeaderLabels(column_names) for col_idx in range(4): item = QStandardItem(data[col_idx]) model.setItem(0, col_idx, item) self.table.setModel(model)
解决方案2:使用类型注释(兼容旧Python版本)
如果你的Python版本低于3.6(不支持变量类型标注),可以在赋值语句后面加类型注释:
self.table = self.findChild(QTableView, "tableView") # type: QTableView
或者用typing.cast做强制类型转换(需要导入cast):
from typing import cast # ... self.table = cast(QTableView, self.findChild(QTableView, "tableView"))
解决方案3:直接访问UI生成的属性(更简洁)
其实loadUi会自动把UI文件中所有控件(根据objectName)作为实例属性添加到self上。如果你的UI里的表格控件objectName是tableView,那你完全不用调用findChild,直接用self.tableView即可:
class Dialog(QDialog): def __init__(self): super(Dialog, self).__init__() loadUi("dialog.ui", self) # 去掉findChild,直接使用UI生成的属性 def fill_table(self, data): column_names = ["full_name", "mail", "age", "phone_number"] model = QStandardItemModel(1, 4) model.setHorizontalHeaderLabels(column_names) for col_idx in range(4): item = QStandardItem(data[col_idx]) model.setItem(0, col_idx, item) self.tableView.setModel(model)
这种方式下,PyCharm如果配置了Qt相关插件,甚至能自动识别这些动态添加的属性,提供代码补全功能。
以上几种方法都能解决PyCharm的提示问题,推荐第一种或第三种,代码更清晰简洁。记住,这个提示只是静态分析的问题,你的代码本身逻辑是没问题的,运行时不会报错。
备注:内容来源于stack exchange,提问作者SuperNova

