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

PyQt5:如何获取QPushButton对象的自定义动态属性列表

获取QPushButton的自定义动态属性

你遇到的问题核心其实是属性设置对象不对,再加上没有过滤Qt自带的系统属性,咱们一步步来解决:

问题分析

你在代码里把button和test属性设置给了QMenu和QAction对象,而不是目标QPushButton本身。所以当你调用按钮的dynamicPropertyNames()时,自然只能拿到Qt内部的系统属性(那些以_q_开头的),看不到你自己加的自定义属性。

另外,Qt的dynamicPropertyNames()会返回所有动态属性,包括它自己内部用的系统属性,所以咱们需要过滤掉这些系统属性,只保留你自定义的。

解决方案

1. 正确给QPushButton添加自定义属性

如果你是想给按钮加属性,直接在btn对象上调用setProperty()即可:

# 给按钮本身添加自定义属性
btn.setProperty("button", btn)
btn.setProperty("test", "自定义测试值")

2. 过滤系统属性,只保留自定义属性

系统属性通常以_q_开头,我们可以写个小工具方法过滤掉这些属性:

def get_custom_properties(self, obj):
    # 把字节类型的属性名转成字符串,同时过滤系统属性
    return [prop.decode('utf-8') for prop in obj.dynamicPropertyNames() if not prop.startswith(b'_q_')]

3. 如果需要获取菜单/动作的自定义属性

如果你本来就是想给菜单或动作加属性,那需要遍历按钮关联的菜单和子动作来获取:

def list_menu_action_props(self):
    for btn in self.pybutton.values():
        print(f"按钮: {btn.objectName()}")
        # 获取按钮绑定的菜单
        menu = btn.menu()
        if menu:
            # 打印菜单的自定义属性
            print(f"菜单自定义属性: {self.get_custom_properties(menu)}")
            # 遍历菜单下的所有动作
            for action in menu.actions():
                print(f"动作 {action.text()} 的自定义属性: {self.get_custom_properties(action)}")
                # 如果有子菜单,继续遍历子菜单的动作
                sub_menu = action.menu()
                if sub_menu:
                    for sub_action in sub_menu.actions():
                        print(f"子菜单动作 {sub_action.text()} 的自定义属性: {self.get_custom_properties(sub_action)}")

修改后的完整代码示例

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.setMinimumSize(QSize(400, 400))
        texts= ['button1']
        self.pybutton = {}
        list_props = QPushButton('list_props', self)
        list_props.clicked.connect(self.list_props)
        list_props.resize(100,115)
        for x, (text, t) in enumerate(zip(texts, range(300,0,-100))):
            btn = QPushButton(text, self)
            btn.setObjectName('btn{}'.format(x+1))
            btn.resize(100,100)
            btn.move(t,100)
            btn.setStyleSheet('QPushButton::menu-indicator { image: none; }')
            
            # 给按钮本身添加自定义属性
            btn.setProperty("button", btn)
            btn.setProperty("test", "按钮专属自定义值")
            
            menu = QMenu()
            btn.setMenu(menu)
            args = ("button", btn)
            args2 = ("test", btn)
            menu.setProperty(*args)
            for act_text in ("item1", "item2", "item3"):
                action = menu.addAction(act_text, self.status)
                action.setProperty(*args)
                action.setProperty(*args2)
            menu2 = menu.addMenu('menu2')
            action = menu2.addAction('item4', self.status)
            action.setProperty(*args)
            action.setProperty(*args2)
            self.pybutton[str(x+1)] = btn
        self.statusBar()
        
    def status(self):
        action = self.sender()
        btn = action.property("button")
        self.statusBar().showMessage('{} was pressed with button: {}'.format(action.text(), btn.text()))
        
    def get_custom_properties(self, obj):
        # 过滤系统属性,返回可读的自定义属性列表
        return [prop.decode('utf-8') for prop in obj.dynamicPropertyNames() if not prop.startswith(b'_q_')]
        
    def list_props(self):
        for btn in self.pybutton.values():
            print(f"按钮名称: {btn.objectName()}, 按钮文本: {btn.text()}")
            # 获取按钮的自定义属性
            print(f"按钮自定义属性: {self.get_custom_properties(btn)}")
            
            # 额外:获取菜单和动作的自定义属性
            menu = btn.menu()
            if menu:
                print(f"菜单自定义属性: {self.get_custom_properties(menu)}")
                for action in menu.actions():
                    print(f"动作 {action.text()} 的自定义属性: {self.get_custom_properties(action)}")
                    sub_menu = action.menu()
                    if sub_menu:
                        for sub_action in sub_menu.actions():
                            print(f"子菜单动作 {sub_action.text()} 的自定义属性: {self.get_custom_properties(sub_action)}")
            print("---")

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = MainWindow()
    mainWin.show()
    sys.exit( app.exec_() )

运行结果

点击list_props按钮后,控制台会输出清晰的自定义属性列表,不会被系统属性干扰:

按钮名称: btn1, 按钮文本: button1
按钮自定义属性: ['button', 'test']
菜单自定义属性: ['button', 'test']
动作 item1 的自定义属性: ['button', 'test']
动作 item2 的自定义属性: ['button', 'test']
动作 item3 的自定义属性: ['button', 'test']
动作 menu2 的自定义属性: []
子菜单动作 item4 的自定义属性: ['button', 'test']
---

内容的提问来源于stack exchange,提问作者riyadude

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:15:49