为什么 pyqtSlot 装饰器会导致“TypeError: connect() failed"? [英] Why does pyqtSlot decorator cause "TypeError: connect() failed"?

查看:35
本文介绍了为什么 pyqtSlot 装饰器会导致“TypeError: connect() failed"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个 Python 3.5.1 程序,它带有 PyQt5 和一个从 QtCreator ui 文件创建的 GUI,其中 pyqtSlot 装饰器导致TypeError: connect() 在 textChanged(QString) 和edited() 之间失败".

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:connect() 在 textChanged(QString) 和edited() 之间失败".我在这里做错了什么?

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() failed"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆