假设我有一个在Qt Designer中创建的UI文件,我想要动态加载它来操纵小部件,例如:
example.py:
from PyQt5 import QtWidgets, uic
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
uic.loadUi('example.ui', self)
# No code completion here for self.myPushButton:
self.myPushButton.clicked.connect(self.handleButtonClick)
self.show()
是否有一种标准/方便的方法可以在PyCharm(2017.1.4)中为通过这种方式加载的小部件启用代码补完?
目前,我正在使用以下内容(在加载UI文件后在构造函数中编写):
self.myPushButton = self.myPushButton # type: QtWidgets.QPushButton
# Code completion for myPushButton works at this point
我也考虑过这个,但似乎行不通:
assert isinstance(self.myPushButton, QtWidgets.QPushButton)
# PyCharm does not even recognise myPushButton as an attribute of self at this point
最后,我还考虑使用Python存根文件,例如:
example.pyi:
class MyWidget(QtWidgets.QWidget):
def __init__(self):
self.myPushButton: QtWidgets.QPushButton = ...
然而,在example.py之外的代码中可以正确识别myPushButton,但在example.py内部的代码中却不能,这与我所希望的相反。
我还考虑采用第一种方法,但将所有那些行都放在一个永远不会被调用的私有方法中,例如:
example.py:
from PyQt5 import QtWidgets, uic
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent)
uic.loadUi('example.ui', self)
# Code completion now works here for self.myPushButton:
self.myPushButton.clicked.connect(self.handleButtonClick)
self.show()
def __my_private_method_never_called():
self.myPushButton = self.myPushButton # type: QtWidgets.QPushButton
# Or even this (it should have the same effect if this
# function is never called, plus it is less verbose):
self.myPushButton = QtWidgets.QPushButton()
# If I want to make sure that this is never called
# could raise an error at some point:
raise YouShouldNotHaveCalledThisError()
这个方法看起来很好用,而且也让我能够把所有的类型提示代码分组,与其他代码隔离开来。我甚至可以编写一些脚本通过解析UI文件来为我生成所有这些代码行。我只是在想如果读我的代码的人会不会认为这种方法很不正统,即使我清楚地注释了为什么要编写一个在技术上毫无用处的私有函数。