【问题标题】:pyqt5: QPushButton class ,clicked method and the connect [duplicate]pyqt5:QPushButton 类,单击方法和连接 [重复]
【发布时间】:2021-07-07 08:10:59
【问题描述】:

我正在学习pyqt5 看看下面的代码

qbtn = QPushButton('Quit', self)
qbtn.clicked.connect(QApplication.instance().quit)

qtwidgets.py 中的点击签名

 def clicked(self, checked: bool = ...) -> None: ...

clicked 方法的实现在哪里? 它是如何不可调用的,我的意思是它的方法对吗?

  print (qbtn.clicked())

输出: TypeError: native Qt signal is not callable

最后,如果它没有任何实现,它将如何影响 QPushButton ?

print(qbtn)
print (qbtn.clicked)
print (qbtn.clicked.connect)

输出:

<PyQt5.QtWidgets.QPushButton object at 0x7f963ca88160>
<bound PYQT_SIGNAL clicked of QPushButton object at 0x7f963ca88160>
<built-in method connect of PyQt5.QtCore.pyqtBoundSignal object at 0x7f963ca91cc0> 

【问题讨论】:

  • 您在哪里看到“qtwidgets.py 中的点击签名”?
  • 不幸的是我错过了拼写文件的名称它是 .pyi 和 ''i'' 代表接口因此在这种类型的文件中没有实现但主要问题仍然存在(如何点击方法不可调用)
  • qbtn.clicked 不是方法,它是绑定到信号的属性。通过调用其emit 方法(即qbtn.clicked.emit(qbtn.checked()))发出信号。

标签: python pyqt5


【解决方案1】:

应始终牢记两个重要方面:

  1. PyQt(类似于 PySide)是一个binding:它是 Qt 框架的一个接口,因此可以使用标准的 python 函数和方法来访问它;为了创建它,使用了一个特殊的工具 SIP,它实际上创建了从暴露给 python 的对象到 Qt 对象的绑定,反之亦然(对于 PySide,使用的工具称为 Shiboken);
  2. 信号不是方法,它们是可调用对象可以连接到的接口,只要发出信号,这些对象就会被调用,前提是它们具有兼容的签名;

您所指的文件是pyi 文件。来自What does “i” represent in Python .pyi extension?

PyCharm 和其他开发工具使用 *.pyi 文件来提供更多信息,例如 PEP 484 类型提示,而不是从扩展类型和方法的自省中收集到的信息。除了向工具提供信息外,它们不打算被导入、执行或用于任何其他目的。如果您不使用使用 .pyi 文件的工具,则可以放心地忽略此文件。

你提到了下面这行:

def clicked(self, checked: bool = ...) -> None: ...

只有在那些文件中才能找到,就是:一个信息

C++ 中的信号在头文件中声明类似于函数,具有指示信号签名的参数,然后在 Qt(或声明自己的信号的程序)编译时“转换”为信号。[1]

由于 PyQt 和 PySide 是使用上述自动化工具创建的,因此信号可能被列为方法;值得注意的是,官方 PySide 文档列出了信号,甚至包括 def:在 PySide2 中使用了特定的“信号”部分,而在 PySide6 中甚至没有这样标识。

在python绑定中,信号是类的未绑定属性,但是当一个信号被引用作为QObject实例时,PyQt会自动将该实例绑定到信号上以创建一个绑定 em> 信号。

>>> hasattr(QtWidgets.QPushButton.clicked, 'emit')
False
>>> hasattr(QtWidgets.QPushButton().clicked, 'emit')
True

您可以看到信号是通过使用简单的id 动态绑定的(它应该为对象返回一个唯一且恒定的值):

>>> b = QtWidgets.QPushButton()
>>> id(b.clicked)
2971296616
>>> id(b.clicked)
2971299208
# or even:
>>> b.clicked == b.clicked
False

所以,您从一些文档或参考文件中看到的主要是用于创建信号的签名,但也是预期的信号发射/接收器的签名,类似于在 Python 中声明新信号时可以执行的操作(不同之处在于无法定义默认值,例如 QAbstractButton 的 checked=False)。

[1] 这是一个主要的过度简化,我没有足够的 C++ 知识来解释信号创建的具体工作原理,但这只是为了解释。

【讨论】:

    猜你喜欢
    • 2020-11-03
    • 2014-11-17
    • 2018-04-25
    • 2020-12-05
    • 2020-04-30
    • 2013-11-26
    • 2018-10-01
    • 2023-03-25
    • 1970-01-01
    相关资源
    最近更新 更多