You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt技术问题:获取菜单所属按钮的对象名而非菜单项

获取QPushButton菜单对应的按钮

这个问题我之前也碰到过——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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:17:08