Odd "Object not found" problem.

Odd "Object not found" problem.

Anonymous
Not applicable
3,942 Views
1 Reply
Message 1 of 2

Odd "Object not found" problem.

Anonymous
Not applicable
I'm dipping my toes into Python for the first time and I've hit a small problem with a function I wrote that takes a selected object, checks whether it is a joint and if this returns True adds the name to a text field.

The purpose of my code is to create a UI that will allow me to input the names of the joints in my scene that I would normally need to know when building a simple biped character rig. The function that is causing the problems has only one input, the textField into which the name of the selected joint will be written. It works, but only with one textField object in the UI. Should I try to pass in another textField object it causes a runtime error "object not found."

As you can see from the code below the function is only ever called after a button press. The UI is created in such a way as to make the textFields after the buttons, so for the briefest of moments the button commands refer to an object that does not exist. This doesn't seem to matter with the first button/textField combination, and I do not expect it to be the cause of the error in subsequent button/textFields. I may of course be completely wrong on this. 😞

As my UI needs a lot of textFields to be filled the UI building ode is quite hefty. Only the first two button/textField have been set up, though each after the first causes the same error.

I'm using a dictionary to store a list of my UI objects.
widgets = {}

An example of my UI setup.
    #    Left leg layout
widgets = cmds.frameLayout('frameLayoutLegLeft', l='Left Leg', mh=GUIFramePaddingHeight, mw=GUIFramePaddingWidth, p=widgets)
widgets = cmds.rowColumnLayout('layoutLeftLeg', numberOfColumns=3, columnWidth=, p=widgets)
widgets = cmds.text('textHipJointL', l='Hip', al='left', p=widgets)
widgets = cmds.button('buttonHipJointL', l='-<', c='getJointName(widgets)', p=widgets)
widgets = cmds.textField('textFieldHipJointL', p=widgets)
widgets = cmds.text('textKneeJointL', l='Knee', al='left', p=widgets)
widgets = cmds.button('buttonKneeJointL', l='-<', c='getJointName(widgets)', p=widgets)
widgets = cmds.textFieldGrp('textFieldKneeJointL', p=widgets)


The function that works for the first button but errors on all others.

def getJointName(targetTextField, *args):
# in: textField
# return: none

# Get the selected joint
obj = cmds.ls(selection = True)
if cmds.nodeType(obj) == 'joint':
# Set the selected joint as the text field name
cmds.textField(targetTextField, e=True, text=obj)
return


The error as reported by Maya 2011...
# Error: RuntimeError: Object 'testWindow|columnLayout44|tabLayout48|rowColumnLayout43|frameLayoutLegLeft|layoutLeftLeg|textFieldKneeJointL' not found. #


As the full code is a little bit bigger than I can post here I've uploaded the .py file to Dropbox here: https://dl.dropbox.com/u/43129774/test.py. . If anyone has any idea what's going wrong I'd appreciate the help. It's probably just a scoping problem but Maya's error reporting isn't very clear.
0 Likes
3,943 Views
1 Reply
Reply (1)
Message 2 of 2

lee.dunham
Collaborator
Collaborator
couple of tips.
Try enabling show line numbers and show stack trace (in script editor), usually makes it easier to pinpoint the culprit.
Unless neccessary, there is no need to define the name of the widget if your already storing its name.
The purpose for assigning the widgets name to a variable is so that you DONT have to name each field individually.
For example.
widget = mc.textfield()
mc.textfield( widget, e=True, tx='example text' )

will work just fine.
secondly, I find assigning string based commands are very unreliable unless your scoping is spot on.
Instead for simplicity, i recommend lambda or partial (depending on needs).
For example:
def addEntry(field):]
selection = mc.ls( sl=True, type='joint' )
if len( selection ) > 0:
mc.textfield( field, e=True, tx=selection )

#lambda
mc.button( l='Apply', c=lambda *x: addEntry( widget ) )

#partial
mc.button( l='Apply', c=partial( addEntry, widget ) )

The issue will occur however, as you want to have the textfield AFTER the assigning button, that the entry doesn't exist in order to create it (which is probably the same issue your encountering, although in not sure why as the string command isnt executed until the button is pressed - being string an' all). Therefore you can create the widgets, then assign the commands to the buttons after their creation.

widget = mc.window()
widget = mc.columnLayout( adj=True )
widget = mc.textfield()
widget mc.button( l='Apply' )
widget = mc.textfield()
widget mc.button( l='Apply' )
mc.setParent( '..' )

#add commands
mc.button( widget, e=True, c=lambda *x: addEntry( widget ) )
mc.button( widget, e=True, c=lambda *x: addEntry( widget ) )

mc.showWindow( widget )


Although for repetative tasks, you might be better off making things more dynamically driven. In which case, use closure instead.
http://tech-artists.org/forum/showthread.php?2787-dynamic-button-creation

Going back to the task at hand, you can use the mc.ls( sl=True, type='joint' ) and check for valid selection length rather than separately checking the nodes type. I also recommend using a textScrollList or something if joint lists are needed, no point adding a huge amount of textfields and buttons if you can just use one widget.

I hope that helps in some way.
0 Likes