2009-09-23 101 views
6

我需要能夠知道我在動態生成的菜單系統中點擊了哪些項目。我只想知道我點擊了什麼,即使它只是一個字符串表示。Pyqt - QMenu動態填充並點擊

def populateShotInfoMenus(self): 
    self.menuFilms = QMenu() 
    films = self.getList() 

    for film in films: 
     menuItem_Film = self.menuFilms.addAction(film) 
     self.connect(menuItem_Film, SIGNAL('triggered()'), self.onFilmSet) 
     self.menuFilms.addAction(menuItem_Film) 

def onFilmRightClick(self, value): 
    self.menuFilms.exec_(self.group1_inputFilm.mapToGlobal(value)) 

def onFilmSet(self, value): 
    print 'Menu Clicked ', value 

回答

11

而不是直接使用onFilmSet作爲連接的接收器,使用lambda功能,這樣你就可以通過額外的參數:

receiver = lambda film=film: self.onFilmSet(self, film) 
self.connect(menuItem_Film, SIGNAL('triggered()'), receiver) 
+0

我正在尋找什麼,ahhh sweet lambda! – crackerbunny 2009-09-23 22:11:39

1

看看在Qt的屬性系統。你可以動態地添加一個包含字符串或任何你想要的東西的屬性,它定義了這個動作。然後,您可以在插槽中使用sender()方法來獲取調用該插槽的QObject。然後,查詢您設置的屬性並相應地執行任何您想要的操作。

但是,這不是最好的方法來做到這一點。不建議使用sender(),因爲它違反了面向對象的模塊化原則。

最好的方法是使用QSignalMapper類。該類將來自不同對象的信號映射到具有不同參數的相同插槽。

我沒有使用過PyQt,因此我不能給你確切的語法或示例,但是應該不難找到一點研究。

+0

我同意這看起來像使用信號映射器的地方。 – 2009-09-23 16:38:36

1

我想弄清楚一個類似的問題,看了上面的代碼後,這是什麼對我有用。認爲將它們放在一起很好。 =)

self.taskMenu = QtGui.QMenu("Task") 
self.tasks = self.getTasks() #FETCHES A LIST OF LIST 
self.menuTasks = QtGui.QMenu() 
for item in self.tasks: 
    menuItem_Task = self.taskMenu.addAction(item[1]) 
    receiver = lambda taskType=item[0]: self.setTask(taskType) 
    self.connect(menuItem_Task, QtCore.SIGNAL('triggered()'), receiver) 
    self.taskMenu.addAction(menuItem_Task) 

def setTask(self,taskType): 
    print taskType 
1

只是一些額外的信息, 我不知道爲什麼,但lambda函數不會用新PyQt的語法連接工作:

的代碼示例不工作:

self.contextTreeMenuAssignTo = QtGui.QMenu(self) 
    actionAssign = contextMenu.addMenu(self.contextTreeMenuAssignTo) 
    actionAssign.setText("Assign to : ") 
    for user in self.whoCanBeAssignated() : 
     actionAssignTo = QtGui.QAction(user[0] ,self) 
     self.contextTreeMenuAssignTo.addAction(actionAssignTo) 
     actionAssignTo.triggered.connect( lambda userID = user[1] : self.assignAllTo(userID) ) 

但是如果你用替補多舊式連接語法中的最後一行:

self.connect(actionAssignTo, QtCore.SIGNAL('triggered()'), lambda userID = user[1] : self.assignAllTo(userID) )  

一切都很好。 隨着新的連接語法,你只能得到循環:(

+0

對我來說(Qt4)它也適用於新的連接語法,請參閱我的評論到這個答案:http://stackoverflow.com/a/1102089/3224008 – Leistungsabfall 2016-05-02 11:51:58

1

我發現this答案這裏處理這一問題PyQt5的最後一個元素,python3。我不喜歡它的BVAL變量是精確,因爲我不完全理解它,但它花了很長時間找到,所以我想我會在這裏分享。該BVAL從觸發拿起布爾值,並允許任務類型傳遞。

self.taskMenu = QtGui.QMenu("Task") 
self.tasks = self.getTasks() #FETCHES A LIST OF LIST 
self.menuTasks = QtGui.QMenu() 

for item in self.tasks: 
    menuItem_Task = self.taskMenu.addAction(item[1]) 
    receiver = lambda: bVal, taskType=item: self.setTask(bVal, taskType) 
    menuItem_Task.triggered.connect(receiver) 
    self.taskMenu.addAction(menuItem_Task) 

def setTask(self, ignore_bVal, taskType): 
    print taskType 
+0

你不需要'bVal'到'setTask',所以你可以擺脫那個醜陋'ignore_bVal'。唯一的要求是你在'lambda'中插入一個初始參數,這樣'taskType'參數不會被布爾值覆蓋。稍微更健壯(更普遍)的解決方案是用'* args'替換'bVal' - 然後忽略*信號發送的所有可能的*值,並且不改變關鍵字參數。 – ekhumoro 2016-01-28 19:48:50

+0

感謝這個答案,我能夠解決Python3和PyQt5的類似問題。這個想法也可以在這裏看到:https:// github。COM /穆阿邁爾/ mkchromecast /提交/ 719fde94e271f97a2047e84b56d7603a5d8cde09 – muammar 2017-01-11 03:53:59