2016-11-18 111 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

相關問題