def a():
window1 = cmds.window( title="Long Name")
cmds.showWindow(window1)
def b():
if window1.close():
print "windows from a() is closed"
def main():
a()
b()
main()
The code in your example actually throws a NameError.
# Error: NameError: file <maya console> line 6: global name 'window1' is not defined #
That’s because of something known as scope.
https://docs.python.org/2/tutorial/classes.html#python-scopes-and-namespaces
Have a quick skim through this when you find the time to understand a little more about it. Being a bit dry, it might also be helpful to learn by example.
http://stackoverflow.com/questions/291978/short-description-of-python-scoping-rules
In a nutshell, it’s due to the variable window1 being defined in one function, whilst accessed in another. That variable is actually deleted as soon as the function completes. The reason it might have worked for you when posting this question might have been due to you first declaring it outside of any function, thus making it accessible everywhere.
You can think of it as a hierarchy, where a inner function have access to variables declared outside of it, including outside of any function at all.
Now, why does window1.close() throw a “AttributeError”?
type() and dir() might be able to make things a little more clear about what’s happening here.
>>> window1 = cmds.window( title="Long Name")
>>> window1.close()
# Error: AttributeError: file <maya console> line 2: 'unicode' object has no attribute 'close' #
>>> type(window1)
# Result: <type 'unicode'> #
What Python tells you here is that window1 is an instance of a class called “unicode”. As it happens, this class doesn’t have the close member you asked for.
>>> dir(window1)
# Result: ['__add__',
'__class__',
'__contains__',
'__delattr__',
'__doc__',
'__eq__',
'__format__',
...
# Discarded for brievety
Hint: Use type() when you need to know more about what a particular variable actually represents, and dir() to look inside of it and find out what it can do for you. In addition, help() will output some help for you.
>>> help(unicode)
help(unicode)
Help on class unicode in module __builtin__:
class unicode(basestring)
| unicode(string [, encoding[, errors]]) -> object
|
| Create a new Unicode object from the given encoded string.
| encoding defaults to the current default string encoding.
| errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.
|
| Method resolution order:
| unicode
| basestring
| object
|
| Methods defined here:
...
# Discarded for brievety
cmds.window is not object-orientedYou might have expected your window1 variable to work similar to this?
>>> import PySide.QtGui
>>> window = PySide.QtGui.QWidget()
>>> window.show()
>>> window.close()
As it turns out, even though Maya’s GUI may be all PyQt/PySide, the cmds.window command won’t actually return you a Qt instance. It instead returns a unicode object. Just a string.
>>> print window1
'window1'
To make matters a little more confusing, the name you’ve chosen for your variable just so happens to be the exact same name as Maya decided to name the physical window internally, thus returning what looks like the name of your variable. To visualise what’s actually going on, we can create a number of windows, and look at their names.
>>> window1 = cmds.window(title="Long Name")
>>> print window1
'window2'
.>>> window1 = cmds.window(title="Long Name")
>>> print window1
'window3'
To make things a little easier to understand, let’s give it a name ourselves; myWindow. Now we can give cmds.showWindow this string, instead of a variable.
>>> my_window = cmds.window("myWindow", title="Long Name")
>>> cmds.showWindow("myWindow") # This is the same thing
So, to answer your question, to detect if an existing window is already open before opening a new one, you can decide upon a name and check for it.
if not cmds.window("myWindow", query=True, exists=True):
my_window = cmds.window("myWindow", title="Long Name")
cmds.showWindow(my_window)
else:
print "Window was already open."
There are of course many ways of achieving this, but the general idea remains the same even in PySide-land and even standalone apps.
Hope it helps.
Best,
Marcus
cmds.windowis not object-oriented
If you have the code handy, we could try and figure out exactly what it is and maybe that way figure out how to use it properly.
In addition to the dir() and type() I mentioned above, there is a member variable on uninstantiated objects in Python that will show you what it consists of called __mro__.
>>> print MySpecialClass.__mro__
(<class '__main__.MySpecialClass'>, <type 'unicode'>, <type 'basestring'>, <type 'object'>)
For example, here we can see that MySpecialClass is actually a subclass of unicode which is another subclass of basestring. MySpecialClass might then look something like this.
class MySpecialClass(unicode):
def my_method(self):
print "Hello, World"
Remember, the member doesn’t exist on the instantiated version of this class.
>>> my_special_instance = MySpecialClass()
>>> print my_special_instance.__mro__
AttributeError: 'MySpecialClass' object has no attribute '__mro__'
But if the instantiated version is all you have, then you can first get the class using type()
>>> print type(my_special_instance).__mro__
(<class '__main__.MySpecialClass'>, <type 'unicode'>, <type 'basestring'>, <type 'object'>)
So, for the object that you are working with, if you could post here the result of the .__mro__ member variable, we might be able to figure out whether it’s coming from cmds.window or PySide or something else.
dir() returns the following error:
# Error: 'str' object is not callable
# Traceback (most recent call last):
# File "<maya console>", line 19, in <module>
# File "<maya console>", line 17, in main
# File "<maya console>", line 8, in sceneImport
# TypeError: 'str' object is not callable #
The lack of an mro value may indicate that the class is and old-style class, not inheriting from "object"
The error you are seeing when calling dir() looks like you shadowed the builtin dir() function, by assigning a string to the dir variable.
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/59c563ef-d0c9-4d3d-b181-b349e73aea16%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
What Justin said.
We can at least be sure it isn’t a PySide/PyQt object.
Just to clarify, based on your previous example, is this what you did?
>>> print type(window1)
<class 'importSceneUI.ImportScene'>
>>> print type(window1).__mro__
AttributeError: class ImportScene has no attribute '__mro__'
Could you elaborate a little on what role this object played in your question? How are you using it? What does it return?
import pubUI
pubUI.importScene()
Sure, that makes sense. We’ll do another type of digging to get to the bottom of this.
print pubUI
It will tell you the location of that module. You could then head inside and look for def importScene(). Once inside, you might be able to tell what it’s doing and what it is returning.import inspect
print inspect.get_source(pubUi.importScene)
That will output the contents of that function into the script editor.Just so I’m fully understanding what is happening and what you want to do, you want to:
importScene() which will prompt you for a scene to open, in a window that blocks Maya until finished. Similar to the File|Open window.If the importScene() command truly blocks Maya (this is called a “modal”), then you can simply do this.
pubUi.importScene()
myOtherFunction()
And myOtherFunction() will run right after the UI has closed (i.e. returned control to Maya).
If it isn’t blocking, then we’ll need to do something like what Justin and AK Eric suggested above, but before we do we’ll need to know what the window is (Maya or PySide) and what it is called.
Is your company's proprietary module documented in any way? Are there any nice public bits available on this returned UI class? I feel like we are just trying to help you did into generic introspection techniques, when you probably have more info at your fingertips than we do.
I can appreciate that you can't share your companies code here, but there has got to be a way for you to review the code you are using to see what is exposed on this class your company has you using.
Does importScene() block when you call it? Does it return immediately, and if so, what does it return? If the call does indeed block, then it is giving you no opportunity to hook in and get a reference to its UI, before it does its task and ends. In which case, Marcus is right that you would just do whatever you want after the call returns.
Without seeing this code, we will most likely just be lobbing suggestions of how to introspect Maya's lists of UI objects.
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOBCxrcphe69Zfi%3DbEbji82dy2yN%2BbXALS6CFnud5mvkCg%40mail.gmail.com.
Without seeing this code, we will most likely just be lobbing suggestions of how to introspect Maya’s lists of UI objects.
Let’s not underestimate the value of being able to debug Python. When we’re done here, yann19 and anyone in a similar position, should be able to find answers to similar questions with very little effort.
I'm not underestimating the value of debugging. I'm just trying to establish if the obvious routes have been assessed first, like available documentation, or what yann19 knows up front about the code that we cannot see.
Without seeing this code, we will most likely just be lobbing suggestions of how to introspect Maya’s lists of UI objects.
Let’s not underestimate the value of being able to debug Python. When we’re done here, yann19 and anyone in a similar position, should be able to find answers to similar questions with very little effort.
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOB%3Dr4m9bBmh_Kt8L7oiwL9A_q2gkFvOtRB3x1iLw%3DFjqA%40mail.gmail.com.
import animTools
animApp = animTools.launchAnimTools()
print type(animApp)
print type(animApp).__mro__
<class 'animTools.createAnimationToolsUI'>
(<class 'animTools.createAnimationToolsUI'>, <class 'PyQt4.QtGui.QMainWindow'>, <class 'PyQt4.QtGui.QWidget'>, <class 'PyQt4.QtCore.QObject'>, <type 'sip.wrapper'>, <class 'PyQt4.QtGui.QPaintDevice'>, <type 'sip.simplewrapper'>, <class 'animTools_pyAnimToolsUI.Ui_MainWindow'>, <type 'object'>)
I am still pretty interested to know how do one go on from there?
Now that we know it’s a PyQt object, we can do something like this.
import animTools
animApp = animTools.launchAnimTools()
def myCloseEvent(event):
print "Closing!"
widget.closeEvent = myCloseEvent
Or, since you know know the superclass, you can subclass it.
class MyAnimTools(animTools.createAnimationToolsUI):
def closeEvent(self, event):
print "Closing!"
super(MyAnimTools, self).closeEvent(event)
Thus having your own “wrapper” around the original, that you can call instead.
myAnimApp = MyAnimTools()
myAnimApp.show()
However, as the animTools.createAnimationToolsUI object is returned by animTools.launchAnimTools() I can’t be sure if it’s doing anything else to the object before returning it.
To find that out, you can either open that file, or print the source code for the function and have a look.
Get file path to function
>>> import animTools
>>> print animTools
<module 'animTools' from '/somewhere/on/your/server/animTools.py'>
Or print the source code directly
>>> import animTools
>>> import inspect
>>> print inspect.get_source(animTools.launchAnimTools)
class mainWindow(QDialog):
def __init__(self, parent=None):
super(mainWindow, self).__init__(parent)
self.wantToClose = False
def closeEvent(self, event):
self.wantToClose = True
if self.wantToClose:
print "closing"
super(mainWindow, self).closeEvent(event)
#self.importAnim()
else:
print "still opened, not closing"
event.ignore()