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

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效果参考

HDRI浏览器运行效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:03:25