Pylance 在 self.tr() 方法上报错

0 投票
1 回答
40 浏览
提问于 2025-04-14 17:14

我正在用 PySide6 6.6.2 和 Python 3.11.8 开发一个应用程序,一切运行得很好,mypy 也没有问题。不过,正如我在下面的图片中展示的那样,Pylance(在 VSCode 中)一直在抱怨说 self.tr() 不能被访问,尽管实际上它应该可以被任何 QtCore.QObject(因此也包括 QtWidgets.QWidget)访问。实际上,应用程序运行得没有错误,pyside6-lupdatepyside6-lrelease 也都没有问题。

Pylance 抱怨:"无法访问类型 'TestWidget*' 的成员 'tr'。成员 'tr' 是未知的。

这里是示例代码:

from PySide6 import QtWidgets


class TestWidget(QtWidgets.QWidget):

    def __init__(self):
        super(TestWidget, self).__init__()
        self.setLayout(QtWidgets.QVBoxLayout())
        self.layout().addWidget(QtWidgets.QLabel(self.tr("Hello World!")))

据我所知,Qt 的类型定义文件是和库一起打包的。为什么只有这个特定的方法不能正常工作呢?为什么我需要手动为一个方法添加类型定义,而整个包的其他部分都能正确检查类型(例如,self.setLayoutself.layout() 都能正确检查)?这让我觉得可能是我使用 QTranslator 的方式有问题,而不是库本身的问题。

我尝试这样手动实现 self.tr()

from PySide6 import QtWidgets, QtCore


class TestWidget(QtWidgets.QWidget):

    def __init__(self):
        super(TestWidget, self).__init__()
        self.setLayout(QtWidgets.QVBoxLayout())
        self.layout().addWidget(QtWidgets.QLabel(self.tr("Hello World!")))

    def tr(self, text: str) -> str:
        return QtCore.QCoreApplication.translate("TestWidget", text)

这样做让 Pylance 满意,应用程序仍然可以正常工作。不过,我觉得很奇怪,为什么我需要手动实现这个方法,而 文档 本身也在使用它们(而且如果我直接下载那个示例,还是会出现同样的错误)。

有没有人能帮我理解发生了什么?

1 个回答

1

正如@musicamante在回复中提到的,QObject.tr()是一个C++中的静态方法,专门用于QObject类。文档中明确说明:

不幸的是,由于Qt实现tr()的方式,PyQt6无法完全复制它的行为。[...] PyQt6的行为并不理想,未来可能会有所改变。建议使用translate(),而不是tr()。这样可以确保在当前和未来的PyQt6版本中都能正常工作,并且更容易在Python和C++代码之间共享消息文件。

因此,我写的实现方式可能是个不错的选择,使用QtCore.QCoreApplication.translate(),如果需要的话,可以为你的类手动实现self.tr()

以下是上面链接中的示例:

from PySide6 import QtCore
class A(QtCore.QObject):
    def hello(self):
        return QtCore.QCoreApplication.translate('A', "Hello")

a = A()
a.hello() # Correctly translated

撰写回答