2009-09-23 55 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