#!/usr/bin/env python # -*- coding: utf-8 -*- from PySide2 import QtWidgets, QtCore, QtGui import maya.cmds as cmds import os class DNABrowserWidget(QtWidgets.QWidget): dna_selected = QtCore.Signal(str) # 信号:当DNA被选中时发出 def __init__(self, dna_path, img_path, parent=None): super().__init__(parent) self.dna_path = dna_path self.img_path = img_path self.setup_ui() self.scan_dna_files() self.update_grid() def setup_ui(self): # 创建主布局 self.main_layout = QtWidgets.QVBoxLayout(self) self.main_layout.setContentsMargins(0, 0, 0, 0) # 创建流式布局容器 self.flow_widget = QtWidgets.QWidget() self.flow_layout = FlowLayout(self.flow_widget) self.flow_layout.setSpacing(5) # 创建滚动区域 self.scroll_area = QtWidgets.QScrollArea() self.scroll_area.setWidgetResizable(True) self.scroll_area.setWidget(self.flow_widget) self.scroll_area.setStyleSheet(""" QScrollArea { border: none; background-color: transparent; } QScrollBar:vertical { border: none; background: #F0F0F0; width: 8px; margin: 0px; } QScrollBar::handle:vertical { background: #CCCCCC; border-radius: 4px; min-height: 20px; } QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical { height: 0px; } """) self.main_layout.addWidget(self.scroll_area) def scan_dna_files(self): """扫描DNA文件夹并建立索引""" self.dna_files = {} if not os.path.exists(self.dna_path): cmds.warning(f"DNA path not found: {self.dna_path}") return if not os.path.exists(self.img_path): cmds.warning(f"Image path not found: {self.img_path}") return for file in os.listdir(self.dna_path): if file.endswith('.dna'): name = os.path.splitext(file)[0] dna_file = os.path.join(self.dna_path, file).replace("\\", "/") # 直接在img目录下查找图片 img_file = None for ext in ['.jpg', '.png', '.jpeg']: img_path = os.path.join(self.img_path, f"{name}{ext}").replace("\\", "/") if os.path.exists(img_path): img_file = img_path break self.dna_files[name] = { 'dna_path': dna_file, 'img_path': img_file } # 打印调试信息 print(f"DNA file: {name}") print(f" DNA path: {dna_file}") print(f" Image path: {img_file}") print(f" Image exists: {bool(img_file and os.path.exists(img_file))}") def update_grid(self): """更新DNA网格""" # 清除现有按钮 for i in reversed(range(self.flow_layout.count())): self.flow_layout.itemAt(i).widget().deleteLater() # 计算按钮大小 - 减小到原来的1/4左右 container_width = self.flow_widget.width() or 300 button_width = (container_width - 60) // 6 # 每行6个按钮 button_height = int(button_width * 1.2) # 保持宽高比 # 创建DNA样本按钮 for name, info in self.dna_files.items(): dna_btn = self.create_dna_button(name, info, button_width, button_height) self.flow_layout.addWidget(dna_btn) def create_dna_button(self, name, info, width, height): """创建DNA按钮""" btn = QtWidgets.QPushButton() btn.setFixedSize(width, height) # 创建按钮布局 layout = QtWidgets.QVBoxLayout(btn) layout.setContentsMargins(2, 2, 2, 2) layout.setSpacing(1) # 创建图标标签 icon_label = QtWidgets.QLabel() icon_label.setAlignment(QtCore.Qt.AlignCenter) if info['img_path']: pixmap = QtGui.QPixmap(info['img_path']) scaled_pixmap = pixmap.scaled( width - 4, height - 16, QtCore.Qt.KeepAspectRatio, QtCore.Qt.SmoothTransformation ) icon_label.setPixmap(scaled_pixmap) else: icon_label.setText("No Image") icon_label.setStyleSheet("color: #FFFFFF; font-size: 8px;") # 改为白色 # 创建文本标签 text_label = QtWidgets.QLabel(name) text_label.setAlignment(QtCore.Qt.AlignCenter) text_label.setStyleSheet("color: #FFFFFF; font-size: 8px;") # 改为白色 layout.addWidget(icon_label) layout.addWidget(text_label) # 设置样式 - 保持黑色背景,文字改为白色 btn.setStyleSheet(""" QPushButton { background-color: #303030; border: 1px solid #202020; border-radius: 5px; padding: 2px; color: #FFFFFF; /* 按钮文字颜色改为白色 */ } QPushButton:hover { background-color: #404040; border: 1px solid #303030; } QPushButton:pressed { background-color: #202020; } """) btn.setProperty('dna_path', info['dna_path']) btn.clicked.connect(lambda: self.on_dna_selected(info['dna_path'])) return btn def on_dna_selected(self, dna_path): """当DNA被选中时发出信号""" self.dna_selected.emit(dna_path) class FlowLayout(QtWidgets.QLayout): def __init__(self, parent=None): super().__init__(parent) self.itemList = [] self.spacing_x = 5 self.spacing_y = 5 def addItem(self, item): self.itemList.append(item) def count(self): return len(self.itemList) def itemAt(self, index): if 0 <= index < len(self.itemList): return self.itemList[index] return None def takeAt(self, index): if 0 <= index < len(self.itemList): return self.itemList.pop(index) return None def expandingDirections(self): return QtCore.Qt.Orientations(QtCore.Qt.Orientation(0)) def hasHeightForWidth(self): return True def heightForWidth(self, width): height = self.doLayout(QtCore.QRect(0, 0, width, 0), True) return height def setGeometry(self, rect): super().setGeometry(rect) self.doLayout(rect, False) def sizeHint(self): return self.minimumSize() def minimumSize(self): size = QtCore.QSize() for item in self.itemList: size = size.expandedTo(item.minimumSize()) return size def doLayout(self, rect, testOnly): x = rect.x() y = rect.y() lineHeight = 0 for item in self.itemList: widget = item.widget() spaceX = self.spacing_x spaceY = self.spacing_y nextX = x + item.sizeHint().width() + spaceX if nextX - spaceX > rect.right() and lineHeight > 0: x = rect.x() y = y + lineHeight + spaceY nextX = x + item.sizeHint().width() + spaceX lineHeight = 0 if not testOnly: item.setGeometry(QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint())) x = nextX lineHeight = max(lineHeight, item.sizeHint().height()) return y + lineHeight - rect.y() def create_browser(dna_path, img_path, parent=None): """创建并返回DNA浏览器实例""" return DNABrowserWidget(dna_path, img_path, parent)