PyQt技术问题:获取菜单所属按钮的对象名而非菜单项
这个问题我之前也碰到过——Qt里用sender()默认拿到的是触发信号的QAction(菜单项),要定位到承载菜单的那个QPushButton确实得用点小技巧,给你两种实用的解决方案:
方法1:给QAction绑定按钮数据
创建菜单项时,用setData()把对应的按钮存进去,槽函数里直接从菜单项的data中取出按钮,这种方法直观且可靠。
from PyQt5.QtWidgets import QMainWindow, QPushButton, QMenu, QAction, QApplication import sys class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setMinimumSize(400, 400) buttons = ['button1','button2','button3'] self.pybutton = {} x = 0 t = 0 for btn_name in buttons: t += 100 x += 1 # 创建按钮 btn = QPushButton(btn_name, self) btn.move(t, 50) self.pybutton[str(x)] = btn # 创建菜单和菜单项 menu = QMenu(self) action1 = QAction("菜单项1", self) action2 = QAction("菜单项2", self) menu.addAction(action1) menu.addAction(action2) # 给每个菜单项绑定对应的按钮 action1.setData(btn) action2.setData(btn) # 连接信号到槽函数 action1.triggered.connect(self.on_menu_action_triggered) action2.triggered.connect(self.on_menu_action_triggered) btn.setMenu(menu) def on_menu_action_triggered(self): action = self.sender() if action: # 从菜单项数据中取出按钮 button = action.data() if button: print(f"选中的菜单项属于按钮: {button.text()}") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
方法2:用Lambda传递按钮参数
在连接信号时,通过lambda表达式直接把按钮作为参数传递给槽函数,这样槽函数可以直接拿到目标按钮。注意要给lambda的参数赋值btn=btn,避免Python闭包的陷阱。
from PyQt5.QtWidgets import QMainWindow, QPushButton, QMenu, QAction, QApplication import sys class MainWindow(QMainWindow): def __init__(self): super().__init__() self.setMinimumSize(400, 400) buttons = ['button1','button2','button3'] self.pybutton = {} x = 0 t = 0 for btn_name in buttons: t += 100 x += 1 btn = QPushButton(btn_name, self) btn.move(t, 50) self.pybutton[str(x)] = btn menu = QMenu(self) action1 = QAction("菜单项1", self) action2 = QAction("菜单项2", self) menu.addAction(action1) menu.addAction(action2) # 用Lambda传递按钮参数,注意btn=btn的写法 action1.triggered.connect(lambda checked, btn=btn: self.on_menu_action_triggered(btn)) action2.triggered.connect(lambda checked, btn=btn: self.on_menu_action_triggered(btn)) btn.setMenu(menu) def on_menu_action_triggered(self, button): # 直接使用传递过来的按钮 print(f"选中的菜单项属于按钮: {button.text()}") if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
另外提一句,不建议通过action.parent().parent()这种链式调用找按钮——因为菜单的父对象不一定是按钮(比如示例中菜单的父是主窗口),这种方法容易出问题,还是上面两种方法更稳妥。
内容的提问来源于stack exchange,提问作者riyadude
相关产品推荐
相关产品推荐

