Here’s a really minimal example. MGui does more of this, including multicast delegates and pymel-style dot access to properties, but this is a cheap way to make extensible widgets:
class Widget(object):
CMD = cmds.control
def __init__(self, *args, **kwargs):
self.widget = self.CMD(*args, **kwargs)
def set(self, **kw):
flags = {'e': True}
flags.update(**kw)
self.CMD(self.widget, **flags)
def get(self, **kw):
flags = {'q': True}
flags.update(**kw)
self.CMD(self.widget, **flags)
def __repr__(self):
return self.widget
class Button(Widget):
CMD = cmds.button
def __init__(self, *args, **kwargs):
super(Button, self).__init__(*args, **kwargs)
self.set(command = self.clicked)
def clicked(*_):
print "clicked"
class OtherButton(Button):
def clicked(self, *_):
super(OtherButton, self).clicked(*_)
print "and did other stuff on", self
w = cmds.window()
c = cmds.columnLayout()
b = Button("button")
b2 = OtherButton("special button")
cmds.showWindow(w)
if you wanted to call the functionality from outside you could just do “b2.clicked()” although that’s bad practice. If “I can click or I can call” is the goal, then:
class Button(Widget):
CMD = cmds.button
def __init__(self, *args, **kwargs):
super(Button, self).__init__(*args, **kwargs)
self.set(command = self.clicked)
self.execute = lambda ignore: None
def clicked(self, *_):
print "clicked"
You can replace execute with some other function that does the hard work but can be managed independently: for example you could tack this on to the end:
b2.execute = lambda x: cmds.polyCube()
would make button to create a cube, but you could split the ‘execute’ functionality from the pure UI stuff by calling execute in preference to clicked. And obviously it could be more elaborate than a dumb lambda. I usually make handlers pass themselves in so it’s easy to write generic handlers that can tell which widget called them