2017-06-05 138 views
1

我在使用Python 3,PyQt5和Qt5的應用程序中有語法/理解問題。我不確定其中哪些導致了問題。Python/PyQt/Qt QMenu QAction語法

我負責移植一個在Windows下運行的GUI應用程序到Linux,以及更新版本的庫。我無法訪問在Windows下運行的原始文件。

在幾個地方我看到:

menu = QMenu(self) 
action = menu.addAction("Some string") 
action.triggered[()].connect(self.handler) 

我想這用來工作。我正在移植到Python 3.5,PyQt 5.7 & Qt 5.7。我有理由相信這些代碼是針對這些代碼的早期版本編寫的。

現在執行它會在action.triggered[()]段上生成'there is no matching overloaded signal'錯誤。

通過猜測和看幾個例子,我發現某處,我已經改變了最後一行:

action.triggered.connect(self.handler) 

,似乎現在的工作。

有人可以解釋原始的triggered[()]語法意思/工作,以及哪個「產品」有明顯的變化 - 能夠閱讀這個變化的位置會很好嗎?我的替換是否正確/相同的行爲是triggered

回答

2

相關的變化發生在PyQt-5.3中。它是而不是完全安全,只是刪除舊的語法,因爲這可能很容易在當前和未來的代碼中創建一個微妙的錯誤。

問題是,某些信號如triggered將始終發送默認布爾值,除非您採取措施消除它。 Qt的定義了這些信號是這樣的:

triggered(bool checked = false) 

PyQt的先前實施的這兩個重載:

triggered(bool checked) 
    triggered() 

,如果你想明確地選擇後者超載,你必須使用以下略顯尷尬的語法時才:

triggered[()].connect(slot) 

但是現在不再是一個選項,因爲只實現了第一個重載。因此,要獲得準確相同的行爲,就必須自動換行這樣的處理程序:

triggered.connect(lambda checked: slot()) 

或裝飾這樣的:

@QtCore.pyqtSlot() 
    def handleTriggered(self): 
     pass 

否則,很容易陷入一個小陷阱。想象一下,你有一個像這樣定義的方法:

def frobnicate(self, foobar=True): 
     if foobar: 
      # do something nice 
     else: 
      # empty my home directory without prompting 

後來,你決定掛鉤這份長達一個按鈕,像這樣:

self.button.clicked.connect(self.frobnicate) 

這一切似乎完全沒有問題,直到你發現該clicked信號工作就像triggered,始終把False默認...

當然,如果你是絕對肯定,你將從來沒有連接插槽,如triggeredclicked信號參數,你可以逃脫連接他們所有在上面顯示的簡單化的方式。但是,真的,這只是一個等待發生的事故...

+0

_This_是我希望的答案!您能否澄清_what_(語法上)''觸發[()]'是什麼意思?我是Python的新手。那是「一個數組(')'」? – JonBrave

+1

@JonBrave。參數類型的元組用於選擇所需的特定超載。 '()'是空元組,意思是:選擇沒有參數的重載。 – ekhumoro

+1

@JonBrave。我應該補充說,信號是實現['__getitem__'方法]的自定義python對象(https://docs.python.org/3/reference/datamodel.html#object.__getitem__)。它們在概念上更像是一個'dict'(映射)而不是一個數組 - 儘管在某種程度上,python的duck-typing允許它們以相同的方式處理。 – ekhumoro