PyQt5:如何获取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
相关产品推荐
相关产品推荐

