Skip to content

Instantly share code, notes, and snippets.

@Onefabis
Last active December 13, 2018 06:50
Show Gist options
  • Save Onefabis/880764ea5b1379a7c06f8193318c02e5 to your computer and use it in GitHub Desktop.
Save Onefabis/880764ea5b1379a7c06f8193318c02e5 to your computer and use it in GitHub Desktop.
Custom slider for maya
from PySide import QtGui,QtCore
import maya.OpenMayaUI as mui
import shiboken
import sys
class AttrFieldGroup(QtGui.QWidget):
valueChanged = QtCore.Signal(float)
def __init__(self, parent=None):
super(AttrFieldGroup, self).__init__(parent)
# Set the range of the slider and inital value
self.minRange = -100
self.maxRange = 100
self.zero = 0
# Create dummy button to prevent missimg press on the slider
self.dummyB = QtGui.QPushButton ( self )
self.dummyB.setGeometry( QtCore.QRect( 15, 17, 160, 23 ) )
# Create input field
self.input = QtGui.QLineEdit(self)
# Alignment of the text inside the input field
self.input.setAlignment(QtCore.Qt.AlignCenter)
# Validator to limit the input values to the numbers
self.inputValidator = QtGui.QDoubleValidator()
self.inputValidator.setDecimals(0)
self.input.setValidator(self.inputValidator)
self.input.editingFinished.connect(self.fieldEdited)
self.input.textChanged.connect(self.inputCheck)
# Create slider
self.slider = QtGui.QSlider(self)
self.slider.setOrientation(QtCore.Qt.Horizontal)
self.slider.setRange( self.minRange, self.maxRange )
self.slider.setGeometry(15, 0,160,50)
self.slider.setSingleStep(1)
# Attach slider to the different behaviours (move, press, release the handle)
self.slider.sliderMoved.connect(self.sliderMoved)
self.slider.sliderPressed.connect(self.sliderPressed)
self.slider.sliderReleased.connect(self.sliderReleased)
# Set initial value of the slider to zero
self.setValue( self.zero, 'st' )
# Create 'close button' with connected 'close' function
self.but = QtGui.QPushButton( 'x', self )
self.but.pressed.connect( self.winClose )
#self.label.setAlignment( QtCore.Qt.AlignCenter )
self.but.setGeometry( 178, 18, 13, 15 )
# Create combo box
self.comboBox = QtGui.QComboBox( self )
self.comboBox.addItem( 'Item 1' )
self.comboBox.addItem( 'Item 2' )
self.comboBox.addItem( 'Item 3' )
self.comboBox.addItem( 'Item 4' )
self.comboBox.currentIndexChanged.connect(self.changeComboB)
if int(mc.about(v=1)[3]) <= 5:
self.comboBox.setStyleSheet( 'QComboBox{background-color: rgba(30,30,30,180);border-radius: 2px;border: 1px solid #767676; color:#c5c5c5 } QComboBox::drop-down{border: none} QComboBox::down-arrow{ image: url(:/arrowDown.png); padding: 1px 1px 0 0 }' )
else:
self.comboBox.setStyleSheet( 'QComboBox{background-color: rgba(30,30,30,180);border-radius: 2px;border: 1px solid #767676; color:#c5c5c5 } QComboBox::drop-down{border: none} QComboBox::down-arrow{ image: url(:/popupMenuIcon.png)}' )
self.comboBox.setGeometry( 15, 35, 64, 16 )
# Create checkbox
self.chBox = QtGui.QCheckBox( '',self )
#self.chBox.setGeometry( 15, 80, 20, 20 )
self.chBox.move(92, 35)
# Change the style of the checkbox
if int(mc.about(v=1)[3]) <= 5:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0 0 0 2px; image: url(:/checkboxOff.png)}' )
else:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOff.png)}' )
self.chBox.setCheckState(QtCore.Qt.Unchecked)
self.chBox.stateChanged.connect( self.chBoxChange )
self.chBoxChange()
# Drop shadow effect for any element (template)
#shad = QtGui.QGraphicsDropShadowEffect(self)
#shad.setBlurRadius( 4 )
#shad.setColor( 'black' )
#shad.setOffset( 0 )
#self.label.setGraphicsEffect( shad )
# Tweak elements style
self.slider.setStyleSheet('QSlider::groove:horizontal {height: 5px;padding: 0 4px;border: 1px solid #767676;border-radius: 2px;background: rgba(30,30,30,180);filter:alpha(opacity=50);} QSlider::handle:horizontal { height: 10px; width 5px; margin: -5px -5px;background-color: #e46b00;border-radius: 2px; border: 1px solid #a24c00 } QSlider::handle:horizontal:hover{background-color: #eb7b19;border: 1px solid #c25c02;} ')
self.input.setStyleSheet('QLineEdit{background: rgba(30,30,30,180);border-radius: 2px; border: 1px solid #767676;padding-bottom:1px}')
self.but.setStyleSheet('QPushButton{background-color:#575757; color:#c5c5c5; padding: 0 0 2px 1px; border-radius: 2px; border: 1px solid #3c3a37;} QPushButton:hover{background-color:#6e6e6e;} QPushButton:pressed{background-color:#363636}')
self.input.setGeometry(( 100*(self.zero-self.minRange))/(self.maxRange-self.minRange)*1.6-(((100*(self.zero-self.minRange))/(self.maxRange-self.minRange))/50.0-1)*5, 0,30,18)
self.dummyB.setStyleSheet( 'QPushButton{background-color: rgba(30,30,30,1);border: none;} ' )
def switchWindow( self ):
LightTween().valPrint()
def switchSimple( self ):
LightTween().valPrint()
# Function called when combobox switched
def changeComboB( self ):
sItem = self.comboBox.currentIndex()
print sItem
def chBoxChange ( self ):
if self.chBox.isChecked():
self.chBox.setText('Selected')
if int(mc.about(v=1)[3]) <= 5:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0 0 0 2px; image: url(:/checkboxOn.png)}' )
else:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOn.png)}' )
else:
self.chBox.setText('Unselected')
if int(mc.about(v=1)[3]) <= 5:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0 0 0 2px; padding: 0; image: url(:/checkboxOff.png)}' )
else:
self.chBox.setStyleSheet( 'QCheckBox{background-color: rgba(30,30,30,180);border-radius: 2px; width: 67px; height: 14px; spacing: 0; border: 1px solid #767676; color:#c5c5c5 } QCheckBox::indicator{width: 14px; height: 14px; margin: 0; padding: 0; image: url(:/checkboxOff.png)}' )
# 'Simple' function called from RMB menu
def value(self):
return float(self.input.text())
# Function called to set the slider to initial value defined by self.zero variable
def setValue(self, v, stQ ):
self.input.setText("%0.0f" % float(v))
if stQ == 'ed':
self.fieldEdited()
# Function called by moving the slider handle
def sliderMoved(self, val):
self.input.setText('%0.0f' % (val))
self._emitValueChanged()
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange)
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18)
#print val/1.00
# Function called when mouse cursor click on the slider but outside the handle
def sliderPressed(self):
val = self.slider.value()
self.input.setText('%0.0f' % (val))
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange)
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18)
self._emitValueChanged()
# Function performed by release of the slider handle
def sliderReleased(self):
val = float(self.input.text())
LightTween().valPrint( val )
# Function to limit input text field number to the range limit of the slider
def inputCheck(self):
val = self.input.text()
if val and val != "-" and val[0] != 'e':
val = float( self.input.text() )
maxNum = [ str( abs( self.minRange ) ), str( abs( self.maxRange ) ) ]
if val > self.maxRange or val < self.minRange:
if val < 0 and val != self.minRange:
newVal = str(val)[:len ( maxNum[0] )]
self.input.setText(newVal)
elif val > 0 and val != self.maxRange:
newVal = str(val)[:len ( maxNum[1] )-1]
self.input.setText(newVal)
# Function performed when 'Enter' key pressed with the input field in focus
def fieldEdited(self):
val = float(self.input.text())
slval = float(self.slider.value())
if slval != val:
LightTween().valPrint( val )
self.slider.setValue(int(val) )
percentV = 100*(val-self.minRange)/(self.maxRange-self.minRange)
self.input.setGeometry( percentV*1.6-(percentV/50.0-1)*5, 0,30,18)
def _emitValueChanged(self):
self.valueChanged.emit(float(self.input.text()))
# Function to close the window by 'close' button
def winClose(self):
if mc.window( 'LightTween', ex=1):
mc.deleteUI( 'LightTween', wnd=1 )
class LightTween ( object ):
def __init__( self ):
pass
def LightTweenUI ( self ):
try:
if mc.window( 'LightTween', ex=1 ):
mc.deleteUI( 'LightTween', wnd=1 )
except: pass
mayaWin = shiboken.wrapInstance( long( mui.MQtUtil.mainWindow() ), QtGui.QWidget )
# Create the main window
windowName = 'LightTween'
self.win = QtGui.QMainWindow( mayaWin )
# Create the name for the main window
self.win.setObjectName( windowName )
# Create the main widget
self.widget = QtGui.QWidget()
# Make the window 'frameless', without title head
self.win.setWindowFlags( QtCore.Qt.Window | QtCore.Qt.FramelessWindowHint )
# Make the window 'transparent', allowing selection behind it
self.win.setAttribute( QtCore.Qt.WA_NoSystemBackground, 1 )
self.win.setAttribute( QtCore.Qt.WA_TranslucentBackground, 1 )
self.win.setAttribute( QtCore.Qt.WA_PaintOnScreen)
# Set main widget as central inside the window
self.win.setCentralWidget( self.widget )
self.ctrl = AttrFieldGroup( self.widget )
self.ctrl.setGeometry( 0, 0, 194, 50 )
self.sign = AttrFieldGroup()
# 'Under the cursor' positioning functionality (uncomment it)
#pos = QtGui.QCursor.pos()
#mc.window( windowName, e=1, tlc=[pos.y()-25, pos.x()-95 ] )
# Right mouse ( Popup ) menu atteched to the slider
name = mui.MQtUtil.fullName(long(shiboken.getCppPointer(self.win)[0]))
mc.popupMenu(p=name)
mc.menuItem('Dummy item 1')
mc.menuItem('Dummy item 2')
mc.menuItem('Dummy item 3')
self.win.show()
def valPrint( self, val ):
print val
# Launch the script
LightTween().LightTweenUI()
@Onefabis
Copy link
Author

Function 'inputCheck' will filter the input value and limit user to enter the value bigger than 'self.maxRange' and smaller than 'self.minRange' pre-defined in the script to prevent slider to perform unpredictable drawing and performing

@Onefabis
Copy link
Author

Create popup menu in a simpler way, also added a function tha check for value printing from the input field or from the slider, but presepving duble printing of the result.

@Onefabis
Copy link
Author

clip2net_160623213517

@Onefabis
Copy link
Author

Onefabis commented Jul 5, 2016

Update the slider with transparent controller behind the scroller to prevent unnecessary focus loosing from the slider . This consroller has area highlighted with the red border, but initially this border is hided.

image

@Onefabis
Copy link
Author

Onefabis commented Jul 5, 2016

Update the slider with the RMB menu, sombobox (option menu) and checkbox

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment