2016-11-18 105 views
1

我有这个Python 3.5.1程序与PyQt5和从QtCreator ui文件创建的pyqtSlot装饰器导致“TypeError:连接()失败之间textChanged(QString)和编辑()”的文件。为什么pyqtSlot装饰器会导致“TypeError:connect()failed”?

在重现问题的示例代码中,我有2个自定义类:MainApp和LineEditHandler。 MainApp实例化主GUI(来自文件“mainwindow.ui”)并且LineEditHandler处理QLineEdit对象。 LineEditHandler存在的原因是将大部分与QLineEdit对象相关的自定义方法集中在一个类中。它的构造函数需要QLineEdit对象和MainApp实例(在需要时访问其他对象/属性)。

在MainApp中,我将QLineEdit的textChanged信号连接到LineEditHandler.edited()。如果我没有用pyqtSlot()修饰LineEditHandler.edited(),一切正常。如果我为方法使用@pyqtSlot(),则代码运行将失败,并且“TypeError:connect()在textChanged(QString)和edited()之间失败”。我在这里做错了什么?

你可以在mainwindow.ui文件:https://drive.google.com/file/d/0B70NMOBg3HZtUktqYVduVEJBN2M/view

这是示例代码生成问题:

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() 
+0

你在做什么错误的是盲目地使用'pyqtSlot'而不理解它是什么以及什么时候真的需要它。 – ekhumoro

+0

这是一个无法回答的问题。 如果我碰到这个问题,并问这是因为我不是专家,那么每个人在某个时刻都处于同样的位置。 – R01k

回答

0

我不知道什么是错的,但我发现一个解决方法:在框TextChanged信号连接到装饰MainApp方法pyqtSlot调用LineEditHandler.edited():

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) 
     self.lineEdit.textChanged.connect(self._line_edited) 

     @pyqtSlot(name="_line_edited") 
     def _line_edited(self): 
      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 

    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() 
1

你为什么要使用@pyqtSlot

它失败的原因是LineEditHandler不是QObject@pyqtSlot所做的基本上是创建一个真正的Qt插槽,而不是内部使用代理对象(这是没有@pyqtSlot的默认行为)。

+0

我想'@ pyqtSlot',因为edited()是textChanged信号的一个插槽。虽然'@ pyqtSlot'在这里并不是特别需要,但建议将它用于所有插槽。 如果'@ pyqtSlot'不能在QObjects之外使用,为什么它可以在没有类的模块中使用? – R01k

+0

@ R01k。当然不建议将它用于所有插槽 - 我不知道你从哪里获得。 – ekhumoro

+0

我听说过,建议将信号连接到插槽。当它跨线程完成时,这是非常明智的。再次,这正是我所听到的。 – R01k

相关问题