Maya中PySide2为动态生成的图片按钮绑定对应路径点击事件
Maya Qt HDRI浏览器按钮路径绑定实现方案
问题根源
当前代码无法绑定对应路径的核心原因有三点:
- 自定义的
PicButton类没有设计存储对应图片路径的属性,点击事件触发时没有渠道获取对应文件地址 - 原有
paintEvent中的悬停效果逻辑仅定义了变量未实际执行,交互效果不生效 - 遍历文件时使用
os.chdir切换全局工作目录的写法存在隐性bug,且循环中反复覆盖self.my_button属性会导致按钮引用错乱
优化后完整代码
from PySide2 import QtWidgets from PySide2 import QtGui from PySide2 import QtCore from shiboken2 import wrapInstance import maya.OpenMayaUI as omui import glob import os def maya_main_window(): main_window_ptr = omui.MQtUtil.mainWindow() return wrapInstance(int(main_window_ptr), QtWidgets.QWidget) class PicButton(QtWidgets.QAbstractButton): def __init__(self, pixmap, file_path, parent=None): super(PicButton, self).__init__(parent) self.pixmap = pixmap # 直接把当前按钮对应的图片路径存为实例属性 self.file_path = file_path self.pressed.connect(self.on_press) def paintEvent(self, event): painter = QtGui.QPainter(self) # 开启平滑缩放避免缩略图模糊 painter.setRenderHint(QtGui.QPainter.SmoothPixmapTransform) painter.drawPixmap(event.rect(), self.pixmap) # 鼠标悬停时绘制半透明遮罩 if self.underMouse(): painter.fillRect( event.rect(), QtGui.QBrush(QtGui.QColor(150, 150, 150, 128)) ) def enterEvent(self, event): self.update() def leaveEvent(self, event): self.update() def on_press(self): # 点击时直接读取自身存储的路径打印 print(self.file_path) def sizeHint(self): return QtCore.QSize(200, 100) class TestDialog(QtWidgets.QDialog): def __init__(self, parent=maya_main_window()): super(TestDialog, self).__init__(parent) self.setWindowTitle('HDRI浏览器') self.setMinimumSize(650, 600) self.create_widgets() def create_widgets(self): main_layout = QtWidgets.QVBoxLayout(self) # 加滚动区域适配大量HDRI文件 scroll_area = QtWidgets.QScrollArea() scroll_area.setWidgetResizable(True) scroll_content = QtWidgets.QWidget() grid_layout = QtWidgets.QGridLayout(scroll_content) # 网格布局每行放3个按钮,可自行调整列数 col_count = 3 pathToHdris = "D:/CG_CONTENT/HDRIS/HDRI_BROWSER/" # 不切换工作目录,直接拼接完整路径搜索jpg hdri_list = glob.glob(os.path.join(pathToHdris, "*.jpg")) for idx, hdri_path in enumerate(hdri_list): pixmap = QtGui.QPixmap(hdri_path) # 创建按钮时直接传入对应路径 btn = PicButton(pixmap, hdri_path) btn.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) btn.setMaximumSize(200, 100) # 计算行列位置放到网格布局 row = idx // col_count col = idx % col_count grid_layout.addWidget(btn, row, col) scroll_area.setWidget(scroll_content) main_layout.addWidget(scroll_area) if __name__ == "__main__": try: test_dialog.close() test_dialog.deleteLater() except: pass test_dialog = TestDialog() test_dialog.show()
关键改动说明
- 给
PicButton新增file_path入参,创建按钮时就把对应图片的完整路径绑定到按钮实例上,点击时直接读取自身属性即可,完全规避循环绑定信号的闭包问题 - 修复了原有绘制逻辑的bug,新增图片平滑渲染,悬停半透明效果可正常触发
- 移除
os.chdir写法,改用os.path.join拼接路径,不会修改Maya全局工作目录 - 替换原垂直布局为网格布局+滚动区域,支持大量HDRI文件的浏览,每行展示数量可通过
col_count参数自行调整 - 移除循环中无意义的
self.my_button属性覆盖逻辑,避免后续按钮引用错乱
UI效果参考

内容的提问来源于stack exchange,提问作者johancc
相关产品推荐
相关产品推荐

