pyqtSlot装饰器为什么会导致“ TypeError:connect()失败”? [英] Why does pyqtSlot decorator cause "TypeError: connect() failed"?
问题描述
我有这个带有PyQt5的Python 3.5.1程序,以及一个从QtCreator ui文件创建的GUI,其中pyqtSlot装饰器导致 TypeError:textChanged(QString)和edited()之间的connect()失败。
I have this Python 3.5.1 program with PyQt5 and a GUI created from a QtCreator ui file where the pyqtSlot decorator causes "TypeError: connect() failed between textChanged(QString) and edited()".
在重现该问题的示例代码中,我有2个自定义类:MainApp和LineEditHandler。 MainApp实例化主GUI(从文件 mainwindow.ui),并且LineEditHandler处理QLineEdit对象。 LineEditHandler存在的原因是将与QLineEdit对象主要相关的自定义方法集中在一个类中。它的构造函数需要QLineEdit对象和MainApp实例(在需要时访问其他对象/属性)。
In the sample code to reproduce the problem I have 2 custom classes: MainApp and LineEditHandler. MainApp instantiates the main GUI (from the file "mainwindow.ui") and LineEditHandler handles a QLineEdit object. LineEditHandler reason to exist is to concentrate the custom methods that relate mostly to the QLineEdit object in a class. Its constructor needs the QLineEdit object and the MainApp instance (to access other objects/properties when needed).
在MainApp中,我将QLineEdit的textChanged信号连接到LineEditHandler.edited ()。如果我不使用pyqtSlot()装饰LineEditHandler.edited(),则一切正常。如果我对方法使用@pyqtSlot(),则代码运行将失败,并显示 TypeError:textChanged(QString)和edited()之间的connect()失败。我在这里做什么错了?
In MainApp I connect the textChanged signal of the QLineEdit to LineEditHandler.edited(). If I don't decorate LineEditHandler.edited() with pyqtSlot() everything works fine. If I do use @pyqtSlot() for the method, the code run will fail with "TypeError: connect() failed between textChanged(QString) and edited()". What am I doing something wrong here?
您可以在以下位置获取mainwindow.ui文件: https://drive.google.com/file/d/0B70NMOBg3HZtUktqYVduVEJBN2M/view
You can get the mainwindow.ui file at: https://drive.google.com/file/d/0B70NMOBg3HZtUktqYVduVEJBN2M/view
是生成问题的示例代码:
And this is the sample code to generate the problem:
import sys
from PyQt5 import uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import pyqtSlot
Ui_MainWindow, QtBaseClass = uic.loadUiType("mainwindow.ui")
class MainApp(QMainWindow, Ui_MainWindow):
def __init__(self):
# noinspection PyArgumentList
QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
# Instantiate the QLineEdit handler.
self._line_edit_handler = LineEditHandler(self, self.lineEdit)
# Let the QLineEdit handler deal with the QLineEdit textChanged signal.
self.lineEdit.textChanged.connect(self._line_edit_handler.edited)
class LineEditHandler:
def __init__(self, main_window, line_edit_obj):
self._line_edit = line_edit_obj
self._main_window = main_window
# FIXME The pyqtSlot decorator causes "TypeError: connect() failed between
# FIXME textChanged(QString) and edited()"
@pyqtSlot(name="edited")
def edited(self):
# Copy the entry box text to the label box below.
self._main_window.label.setText(self._line_edit.text())
def main():
app = QApplication(sys.argv)
window = MainApp()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
推荐答案
为什么想要使用 @pyqtSlot
?
失败的原因是 LineEditHandler
不是 QObject
。 @pyqtSlot
所做的基本上是创建一个真正的Qt插槽,而不是在内部使用代理对象(这是默认行为,没有 @pyqtSlot
)。
The reason it fails is that LineEditHandler
is not a QObject
. What @pyqtSlot
does is basically creating a real Qt slot instead of internally using a proxy object (which is the default behavior without @pyqtSlot
).
这篇关于pyqtSlot装饰器为什么会导致“ TypeError:connect()失败”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!