# -*- coding: utf-8 -*- from maya import OpenMayaUI, cmds from maya.app.general.mayaMixin import MayaQWidgetDockableMixin #PySide2、PySide両対応 import imp try: imp.find_module('PySide2') from PySide2.QtWidgets import * from PySide2.QtGui import * from PySide2.QtCore import * except ImportError: from PySide.QtGui import * from PySide.QtCore import * try: imp.find_module("shiboken2") import shiboken2 as shiboken except ImportError: import shiboken MAYA_VER = int(cmds.about(v=True)[:4]) MAYA_API_VER = int(cmds.about(api=True)) try: MAYA_WIDNOW = shiboken.wrapInstance(long(OpenMayaUI.MQtUtil.mainWindow()), QWidget) except: MAYA_WIDNOW = None #MayaWindow単独取得関数 def get_maya_window(): try: return shiboken.wrapInstance(long(OpenMayaUI.MQtUtil.mainWindow()), QWidget) except: return None class MainWindow(QMainWindow): def __init__(self, parent = MAYA_WIDNOW): super(MainWindow, self).__init__(MAYA_WIDNOW) class SubWindow(QMainWindow): def __init__(self, parent = MAYA_WIDNOW): super(SubWindow, self).__init__(MAYA_WIDNOW) class DockWindow(MayaQWidgetDockableMixin, QMainWindow): def __init__(self, *args, **kwargs): super(DockWindow, self).__init__(*args, **kwargs) class Callback(object): def __init__(self, func, *args, **kwargs): self.__func = func self.__args = args self.__kwargs = kwargs def __call__(self, *args, **kwargs): cmds.undoInfo(openChunk=True) try: return self.__func(*self.__args, **self.__kwargs) except: raise finally: cmds.undoInfo(closeChunk=True) #右クリックボタンクラスの作成 class RightClickButton(QPushButton): rightClicked = Signal() def mouseReleaseEvent(self, e): if e.button() == Qt.RightButton: self.rightClicked.emit() else: super(self.__class__, self).mouseReleaseEvent(e) class RightClickToolButton(QToolButton): rightClicked = Signal() def mouseReleaseEvent(self, e): if e.button() == Qt.RightButton: self.rightClicked.emit() else: super(self.__class__, self).mouseReleaseEvent(e) #ctrl,shiftでフォーカスが飛ばないカスタムラインエディット class LineEdit(QLineEdit): def keyPressEvent(self, event): key = event.key() if key == Qt.Key.Key_Control or key == Qt.Key.Key_Shift: return else: super(self.__class__, self).keyPressEvent(event) class EditorDoubleSpinbox(QDoubleSpinBox): wheeled = Signal() focused = Signal() keypressed = Signal() mousepressed = Signal() def __init__(self, parent=None): super(self.__class__, self).__init__(parent) self.installEventFilter(self) #ホイールイベントをのっとる def wheelEvent(self,e): pass def eventFilter(self, obj, event): if event.type() == QEvent.FocusIn: self.sel_all_input() self.focused.emit() if event.type() == QEvent.Wheel: delta = event.delta() delta /= abs(delta) shift_mod = self.check_shift_modifiers() ctrl_mod = self.check_ctrl_modifiers() if shift_mod: self.setValue(self.value()+delta/10.0) elif ctrl_mod: self.setValue(self.value()+delta*10.0) else: self.setValue(self.value()+delta) cmds.evalDeferred(self.emit_wheel_event) if event.type() == QEvent.KeyPress: self.keypressed.emit() if event.type() == QEvent.MouseButtonPress: self.mousepressed.emit() return False def emit_wheel_event(self): self.wheeled.emit() #ウェイト入力窓を選択するジョブ def sel_all_input(self): cmds.evalDeferred(self.select_box_all) #スピンボックスの数値を全選択する def select_box_all(self): try: self.selectAll() except: pass def check_shift_modifiers(self): mods = QApplication.keyboardModifiers() isShiftPressed = mods & Qt.ShiftModifier shift_mod = bool(isShiftPressed) return shift_mod def check_ctrl_modifiers(self): mods = QApplication.keyboardModifiers() isCtrlPressed = mods & Qt.ControlModifier ctrl_mod = bool(isCtrlPressed) return ctrl_mod #フラットボタンを作って返す def make_flat_btton(icon=None, name='', text=200, bg=[54, 51, 51], ui_color=68, border_col=180, checkable=True, w_max=None, w_min=None, push_col=120, h_max=None, h_min=None, policy=None, icon_size=None, tip=None, flat=True, hover=True, destroy_flag=False, context=None): button = RightClickButton() button.setText(name) if checkable: button.setCheckable(True)#チェックボタンに if icon: button.setIcon(QIcon(icon)) if flat: button.setFlat(True)#ボタンをフラットに change_button_color(button, textColor=text, bgColor=ui_color, hiColor=bg, mode='button', hover=hover, destroy=destroy_flag, dsColor=border_col) button.toggled.connect(lambda : change_button_color(button, textColor=text, bgColor=ui_color, hiColor=bg, mode='button', toggle=True, hover=hover, destroy=destroy_flag, dsColor=border_col)) else: button.setFlat(False) change_button_color(button, textColor=text, bgColor=bg, hiColor=push_col, mode='button', hover=hover, destroy=destroy_flag, dsColor=border_col) if w_max: button.setMaximumWidth(w_max) if w_min: button.setMinimumWidth(w_min) if h_max: button.setMaximumHeight(h_max) if h_min: button.setMinimumHeight(h_min) if icon_size: button.setIconSize(QSize(*icon_size)) if policy:#拡大縮小するようにポリシー設定 button.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding) if tip: button.setToolTip(tip) if context:#コンテキストメニュー設定 button.setContextMenuPolicy(Qt.CustomContextMenu) button.customContextMenuRequested.connect(context) return button #ウィジェットカラーを変更する関数 def change_widget_color(widget, hibgColor = [100, 140, 180], hitxColor = 255, textColor=200, bgColor=68, baseColor=42, windowText=None): '''引数 widget 色を変えたいウィジェットオブジェクト bgColor 背景色をRGBのリストか0~255のグレースケールで指定、省略可能。 ''' #リスト型でなかったらリスト変換、グレースケールが指定ができるように。 if not isinstance(hibgColor, list): hibgColor = [hibgColor, hibgColor, hibgColor] if not isinstance(hitxColor, list): hitxColor = [hitxColor, hitxColor, hitxColor] if not isinstance(textColor, list): textColor = [textColor, textColor, textColor] if not isinstance(bgColor, list): bgColor = [bgColor, bgColor, bgColor] if not isinstance(baseColor, list): baseColor = [baseColor, baseColor, baseColor] #色指定 bgColor = QColor(*bgColor) textColor = QColor(*textColor) hibgColor = QColor(*hibgColor) hitxColor = QColor(*hitxColor) baseColor = QColor(*baseColor) #ウィジェットのカラー変更 palette = QPalette() palette.setColor(QPalette.Button, bgColor) palette.setColor(QPalette.Background, bgColor) palette.setColor(QPalette.Base, baseColor) palette.setColor(QPalette.Text, textColor) palette.setColor(QPalette.ButtonText, textColor) palette.setColor(QPalette.Highlight, hibgColor) palette.setColor(QPalette.HighlightedText, hitxColor) #ウィンドウテキストの特殊処理 if windowText is not None: if not isinstance(windowText, list): windowText = [windowText, windowText, windowText] windowTextColor = QColor(*windowText) #print windowText palette.setColor(QPalette.WindowText, windowTextColor) # ウィジェットにパレットを設定 widget.setAutoFillBackground(True) widget.setPalette(palette) ''' パレットを使って指定する色は次のものがある。 WindowText Button Light Midlight Dark Mid Text BrightText ButtonText Base Window Shadow Highlight HighlightedText Link LinkVisited AlternateBase NoRole ToolTipBase ToolTipText NColorRoles = ToolTipText + 1 Foreground = WindowText Background = Window // ### Qt 5: remove ''' def change_border_style(button): button. setStyleSheet('QPushButton{border-style:solid; border-width: 2px; border-color: red ; border-radius: 1px;}' +\ 'QPushButton:hover{border-style:solid; border-width: 2px; border-color: red ; border-radius: 1px;}'+\ 'QPushButton:pressed{border-style:solid; border-width: 2px; border-color: red ; border-radius: 1px;}') #ボタンカラーを変更する関数 def change_button_color(button, textColor=200, bgColor=68, hiColor=68, hiText=255, hiBg=[97, 132, 167], dsColor=[255, 128, 128], mode='common', toggle=False, hover=True, destroy=False, dsWidth=1): '''引数 button 色を変えたいウィジェットオブジェクト textColor ボタンのテキストカラーをRGBのリストか0~255のグレースケールで指定、省略可能。 bgColor 背景色をRGBのリストか0~255のグレースケールで指定、省略可能。 ''' #リスト型でなかったらリスト変換、一ケタでグレー指定ができるように。 textColor = to_3_list(textColor) bgColor = to_3_list(bgColor) hiColor = to_3_list(hiColor) hiText = to_3_list(hiText) hiBg = to_3_list(hiBg) dsColor = to_3_list(dsColor) #ボタンをハイライトカラーにする if toggle and button.isChecked(): bgColor = hiColor #ホバー設定なら明るめの色を作る if hover: hvColor = map(lambda a:a+20, bgColor) else: hvColor = bgColor #RGBをスタイルシートの16進数表記に変換 textHex = convert_2_hex(textColor) bgHex = convert_2_hex(bgColor) hvHex = convert_2_hex(hvColor) hiHex = convert_2_hex(hiColor) htHex = convert_2_hex(hiText) hbHex = convert_2_hex(hiBg) dsHex = convert_2_hex(dsColor) #destroy=True #ボタンはスタイルシートで色変更、色は16進数かスタイルシートの色名で設定するので注意 if mode == 'common': button.setStyleSheet('color: '+textHex+' ; background-color: '+bgHex) if mode == 'button': if not destroy: button. setStyleSheet('QPushButton{background-color: '+bgHex+'; color: '+textHex+' ; border: black 0px}' +\ 'QPushButton:hover{background-color: '+hvHex+'; color: '+textHex+' ; border: black 0px}'+\ 'QPushButton:pressed{background-color: '+hiHex+'; color: '+textHex+'; border: black 2px}') if destroy: button. setStyleSheet('QPushButton{background-color: '+bgHex+'; color: '+textHex+'; border-style:solid; border-width: '+str(dsWidth)+'px; border-color:'+dsHex+'; border-radius: 0px;}' +\ 'QPushButton:hover{background-color: '+hvHex+'; color: '+textHex+'; border-style:solid; border-width: '+str(dsWidth)+'px; border-color:'+dsHex+'; border-radius: 0px;}'+\ 'QPushButton:pressed{background-color: '+hiHex+'; color: '+textHex+'; border-style:solid; border-width: '+str(dsWidth)+'px; border-color:'+dsHex+'; border-radius: 0px;}') if mode == 'window': button. setStyleSheet('color: '+textHex+';'+\ 'background-color: '+bgHex+';'+\ 'selection-color: '+htHex+';'+\ 'selection-background-color: '+hbHex+';') ''' ## 最終的に設定する変数 style = '' ## 枠線の色と太さ # border = 'border: 2px solid gray;' border = 'border-style:solid; border-width: 1px; border-color:gray;' ## 枠線の丸み borderRadius = 'border-radius: %spx;' % (30/2) ## ボタンのスタイルを作成 buttonStyle = 'QPushButton{%s %s}' % (border, borderRadius) ## ボタンのスタイルを追加 style += buttonStyle ## 上記のパラメータを設定 button.setStyleSheet(style) ''' ''' #スタイルシート参考 button. setStyleSheet('QPushButton{background-color: cyan; color: black; border: black 2px} +\ QPushButton:hover{background-color: green; color: black; border: black 2px} +\ QPushButton:pressed{background-color: red; color: black; border: black 2px}') ''' def to_3_list(item): if not isinstance(item, list): item = [item]*3 return item #16真数に変換する def convert_2_hex(color): hex = '#' for var in color: #format(10進数, 'x')で16進数変換 var = format(var, 'x') if len(var) == 1: #桁数合わせのため文字列置換 hex = hex+'0'+str(var) else: hex = hex+str(var) return hex #垂直分割線を追加する関数 def make_v_line(): vline = QFrame() vline.setFrameShape(QFrame.VLine) vline.setFrameShadow(QFrame.Sunken) return vline #水平分割線を追加する関数 def make_h_line(): hline = QFrame() hline.setFrameShape(QFrame.HLine) hline.setFrameShadow(QFrame.Sunken) return hline # index :Noneの場合全列処理 def set_header_width(widget, index=None, space=0, min=200): if hasattr(widget.header(), 'setResizeMode'): # PySide resize_mode = widget.header().setResizeMode else: # PySide2 resize_mode = widget.header().setSectionResizeMode def resize_main(index): resize_mode(index, QHeaderView.ResizeToContents) width = widget.columnWidth(index) + space widget.setColumnWidth(index, width) resize_mode(index, QHeaderView.Interactive) if width < 200 and index == 0: widget.setColumnWidth(0,min) return if index is None: count = widget.columnCount() for i in range(count): resize_main(i) else: resize_main(index) #------------------------------------------------------------- #Shift,Ctrlなどのモディファイヤが押されてるかどうかを判定する関数 def check_key_modifiers(modifire): mods = QApplication.keyboardModifiers() isPressed = mods & modifire return bool(isPressed)