Dio*_*ogo 2 python properties python-3.x pyqt5
我有几个关于PyQt5 包的类和pythonpyqtProperty标准内置类的问题:property
为什么要使用pyqtProperty标准属性?下面给出的代码可以两种方式工作。pyqtProperty使用代替 Python 的普通旧式property(用作方法上的装饰器)有什么优势?我知道我必须指定 a 的返回类型pyqtProperty,但为什么我要使用它?
继承pyqtProperty自property? 该属性pyqtProperty.__mro__没有显示(结果是PyQt5.QtCore.pyqtProperty, object)并且我找不到pyqtProperty. PyDoc的命令引用.pyd模块的文件PyQt5.QtCore(不是源代码纯文本文件),并且没有它的存根文件。但该命令help(pyqtProperty)给我的信息与得到的信息非常相似help(property),与官方文档中找到的信息不同。那么,这些信息从何而来?
为什么在 Qobject 设置时执行用@pyqtProperty甚至 用修饰的方法?@property
回到下面给出的代码:属性方法(在@pyqtProperty和两种情况@property下)在创建属性 之前执行_custom_property,这给出了AttributeError. 但这不应该发生,并且对于@property具有常规 python 类的装饰器来说确实不会发生(我也尝试过,下面有一个片段)。当我使用简单的 getter 和 setter 方法(未修饰)时,这种情况根本不会发生(这是正常的)。最奇怪的现象是:AttributeError当我在调试模式下运行时会发生这种情况。在正常模式 ( python main.py) 下,属性方法无论如何都会执行,但不会引发错误。
我使用的是与 Anaconda Distribution、python 3.8 一起安装的 PyQt5 版本 5.9.2。
这是使用 pyuic5 生成的 Ui_MainWindow.py 文件的内容:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(419, 196)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
self.horizontalLayout.setObjectName("horizontalLayout")
self.lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.lineEdit.setObjectName("lineEdit")
self.horizontalLayout.addWidget(self.lineEdit)
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 419, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.lineEdit.setText(_translate("MainWindow", "test"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
Run Code Online (Sandbox Code Playgroud)
main.py这是使用装饰器的文件内容property:
from Ui_MainWindow import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
class MainWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self._custom_property = 1
@property
def custom_property(self):
print("This method is executed")
return self._custom_property
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)
main.py这是使用装饰器的文件内容pyqtProperty:
from Ui_MainWindow import Ui_MainWindow
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import pyqtProperty
class MainWindow(QMainWindow,Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self._custom_property = 1
@pyqtProperty(int)
def custom_property(self):
print("This method is executed")
return self._custom_property
if __name__ == "__main__":
app = QApplication([])
window = MainWindow()
window.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)
我不会将主文件的内容放在没有装饰器的情况下(只需删除@上面代码中的行)。
但这是一个带有property装饰器的简单文件,显示它没有在__init__方法中执行
class Test:
def __init__(self) -> None:
pass
@property
def x(self):
print("This method is not executed in init")
return self._x
def setx(self,value):
self._x = value
if __name__ == "__main__":
a = Test()
Run Code Online (Sandbox Code Playgroud)
pyqtProperty 和 property 之间的区别(不是优点)是,这些属性可以通过 Qt 具有的元对象来访问,最后一个工具用于 Qt 中的各种任务,例如在 QML 中公开属性,能够在 QtStyleSheet 中使用,用于 QPropertyAnimation 等。
propertyaspyqtProperty是一个描述符,因此它不一定从属性继承(这里是如何创建描述符而不从属性继承的示例)。如果你想了解 pyqtProperty 的实现,那么你应该检查源代码qpy/QtCore 文件夹中的 qpycore_pyqtproperty.h 和 qpycore_pyqtproperty.cpp 文件。
方法custom_property调用是由QMetaObject::connectSlotsByName()但我认为这是一个错误引起的。如果方法名称符合特定模式,则此方法尝试建立语义连接:on_<object name>_<signal name>(<signal parameters>)。我指出这是一个错误,因为如果我使用 PySide2 实现相同的逻辑,我不会观察到该行为。
| 归档时间: |
|
| 查看次数: |
3075 次 |
| 最近记录: |