Maya, Mel, QT and You - Interfacing with the QT Designer

Report this File

Final_shot

Views:

39,768

Updated:

Jul 28, 2010

Readership Level:

Intermediate

Tags:

maya, mel, interfaces, highend3d, creativecrash, QT

Maya Versions:

2011

Platforms:

irix, linux, mac, solaris, windows

Owner:

Language:

English

After a rather harrowing weekend I decided that I'd follow through on my promise of a Maya/Mel/QT tutorial, so here it is! So without further ado, here we go:

So today we're going to go through how to make a basic qt interface. What we're going to be creating is an interface that will do 4 things:

  • Get user input to name an object
  • List all the user objects
  • Use a combo box to create an object
  • Rename an object from the list box

The basic premise of this interface will be to make a UI for a user to make an object, with a specific name. It will also list all geometric objects in the scene so we can select and rename the objects.

What we need:

Well to continue with the tutorial to test it out, you'll need a working version of Maya 2011. You can download a trial version from Autodesk's website if you don't already have one. You'll also need the QT toolkit which you'll need to download from Nokia's website. Download the LGPL version, unless you really want to distribute your apps in some other way. (I personally love Open Source software, so that's why I distribute them under a license that is Open Source friendly.) You're also going to need a text editor of some sort. If you're using Windows, I would suggest Notepad++ with the Mel language definition file from CreativeCrash.com.

If you're using a Mac I would suggest either Text Wrangler, Carbon Emacs or if you're familiar with it, Vim. If you choose the latter of the three, I will assume that you are familiar with Vi or are willing to go through the learning process for it. While it has a learning curve, it is EXTREMELY powerful. Emacs is just as powerful as Vi, and I do NOT wish to start that war on here.

If you're using Linux, I'm going to assume you: A) Know what you're doing, since you're running an OS that requires that; and B) Have a text editor such as emacs, vi or some other in mind. However, just for the sake of being thorough, here are 2 choices other than Vi, Emacs or Nano. Nedit has an .edit preferences file on CreativeCrash for syntax highlighting for mel, so that's a useful editor. You can also use jEdit and use this Configuring jEdit for Maya tutorial to get yourself up and running.

As a note, everyone can use jEdit on every platform if they want to since it's built off of Java. I tend to stay away from Java based apps because they're (generally speaking - I'm not knocking java developers) heavier on memory usage, however, jEdit is a VERY powerful editor, has syntax highlighting and code completion, so if you're looking for a great free editor and need cross platform availability, then jEdit is for you.

If you are looking for a very feature rich text editor for Windows, and don't mind spending a bit of money, then I'd suggest E Text Editor. if you're on a Mac, I would suggest Textmate. Both have syntax highlighting for Mel built in (they use the same libraries), so that for me was a huge selling point. They both also have a 30 day free trial, so try before you buy (you don't want to waste the cash if you don't like it).

Now that I've given you way more stuff to choose from (there's a lot to be said about being thorough), let's get started. Since this tutorial is focusing on the creation of the interface and hooking it into the mel code, I'm going to give the code for the creation of everything right here. Save that as whatever you'd like with the extension .mel. I'll be naming mine object_creator_tutorial.mel . It made sense to me. :)

	global proc objectCreator(){
		//If Maya's version is greater than or equal to 2011 go ahead
		if (getApplicationVersionAsFloat() >= 2011){
			//set the scripts directory so we can load our ui file
			string $scriptsDirectory = `internalVar -usd`;
			//load the ui file
			string $objectCreatorWindow = `loadUI -uiFile ($scriptsDirectory+"/object_creator_tutorial.ui")`;
			//show the window
			showWindow $objectCreatorWindow;
			//find all objects in the scene and load their mesh transform name
			updateObjectsInScene;
		}else{
			//You aren't using Maya 2011 if this pops up. The upgrade is worth it! :)
			print "You're using a version of Maya that is incompatible with this script.\n";
		}
	}

	global proc updateObjectsInScene(){
		//to get the meshes available
		string $listObjects[] = `ls -type mesh`;
		//get the transform node
		string $topLevelListObjects[] = `listRelatives -parent -type "transform" $listObjects`;
		//clear the scroll list so no duplicates show up
		textScrollList -e -ra objectScrollList;
		//iterate through and add all the meshes
		for($item in $topLevelListObjects){
			//update the items in the scroll list
			textScrollList -e -a $item objectScrollList;
		}
	}


	//change the object(s) name
	global proc objectRenamer(){
		//select all the items that are active in the list
		string $sel[] = `textScrollList -q -si objectScrollList`;
		//get the users input for the new name
		string $objectNewName = `textField -q -text objectNewName`;
		//rename the object
		rename $sel $objectNewName;
		//deselect everything in the scrollList so we don't change things we don't want to next time
		textScrollList -e -deselectAll objectScrollList;
		//clear all selections
		select -cl;
		//update the scroll list since we just renamed the object
		updateObjectsInScene;
	}

	//create the object
	global proc objectCreation(){
		//get the object we want to create	
		string $createObject = `optionMenu -q -v typeOfObject`;
		//get the name of the object we want to create
		string $objectCreateName = `textField -q -text objectNewName`;
		//create the object
		eval $createObject;
		//get the selected object
		string $sel[] = `ls -sl`;
		if($objectCreateName == ""){
			//do nothing
		}else{
			//rename the selected object
			rename $sel $objectCreateName;
		}
		//update the scroll list since we just created an object
		updateObjectsInScene;
	}

Alright. You've got that saved and you've got everything running. What we're gonna do now is launch the QT Designer. When it launches it will look like this:

main_window

We want to choose "Main Window" from the templates/forms sidebar and then click create. A window will pop up that looks as such:

second_screen

What we're going to do from here is this (I'm not going to provide screenshots for every single nitty gritty detail as most of it should be self explanatory):

  • Resize the window to how large or small we want it
  • Add a layout to contain our objects
  • Add a container to contain our objects
  • Add in our 8 objects that we're going to create
    • A list widget
    • A combo box
    • A line edit
    • 2 labels - one for the line edit and one for the combo box
    • 3 push buttons
      • One for creating our object
      • One for renaming our object
      • One for reloading the list boxes contents
  • Attach the necessary code to each object
  • Add in controls to get the data

It's a fairly long list, but we should be able to accomplish all of this in roughly an hour or two. Alright. Let's get started.

First we're going to click and drag a grid layout from the widget box panel -> layouts to our working area on our layout. Resize it so it's large enough to fit all of our objects (you can tweak it later if it's too small. Now grab a container of some sort (I'm going to use a group box) and drag that into the grid layout. Now we can go ahead and drag all of our objects into that layout. Now one note I would like to make is that when you bring your List Widget over, make ABSOLUTELY sure that you use the List Widget under Item-Based, NOT Model-Based. If you use Model-Based you will never see your results on the screen. You can position them and resize them as you see fit. Here's how mine looks:

third_screen

As I'm sure you've noticed, I've named my objects already. If you haven't gotten to this point, that's alright, I'm going to go through it for each object. If you have, you can skip this part (I'll put a notice as to where it's pertinent to you again). You may however may want to read this paragraph and the next one so you know what options to set where. The first thing we'll want to rename is our Main Window. To do so first select the Main Window in the Object Inspector. Then in the Property Editor scroll down until you see the word window on the left hand side. Simply click in the field next to it and enter in the name you wish to use. Here's a screenshot of that:

fourth_screen

Readers that skipped ahead this part is for you too. Now let's rename our list box and set some options for it. When you select it at the top it should say objectName. We want this to match our mel script, so we'll name it objectScrollList . It should now look like this:

fifth_screen

Now let's also change a few options. We want to change the edit triggers from what it currently is to No Edit Triggers. So twirl down the options and double-click the top option that says No Edit Triggers. At this point we can be done editing this, but if you want you can allow the user to drag and drop the objects to re-order them. To do so make sure that dragEnabled is checked, then change dragDropMode to internalMove and defaultDropAction to MoveAction. You can also set alternating row colors, but it doesn't show very well unless you make a custom color scheme for your ui. Keep selection mode at SingleSelection as well. At the bottom you'll see an option for sorting called sortingEnabled. This is useful, but if you want the drag and drop ability make sure this is NOT checked.

Readers that skipped ahead you can continue skipping again. :) Ok, now let's modify a button. Select any of your buttons. At the top you can rename it to whatever you'd like with the suffix of Button. For mine, I've renamed it to renameObjectButton (with the same naming scheme for the rest of them). Now scroll down to where the list turns green (QAbstractButton) and find the text field. Click that field and type in your name. Done. That's all we're doing for that. You can rename the rest of the buttons in the same manner.

Readers that skipped ahead this part is for you too. After you're done with that we need to give an object name to our line edit field. We're going to name it objectNewName, since that's what's in our script. We're done with that now.

Now we need to modify the combo box. Now for this we're going to give a bunch of really ugly names. The reason for this is because we need to get the actual names of the object creation. We could name them differently and setup a bunch of if else statements, but for this exercise we want to keep it simple. So double click the combo box and click the plus sign at the bottom. Type in polySphere. We're going to do this several more times, so here's the list of names you need to put in.

  • polyCube
  • polyCylinder
  • polyCone
  • polyPlane
  • polyTorus
  • polyPrism
  • polyPyramid
  • polyPipe
  • polyHelix

Readers that skipped ahead you should continue from here. We've omitted the soccer ball and the platonic solids because the code for creating those is ugly and so it looks worse than these already do. :) Alright. We've got our combo box with stuff in it. The only thing left to do is name it. So in objectName, name it typeOfObject as per our mel.

At this point we're almost done! Now all we need to do is connect a few functions to the buttons. So select your Reload Objects button and go to the property editor. Click the big plus sign and select string. Now type in -command in the pop up. Now a new object in the property list will show up under dynamic objects. Next to -command type in the text field updateObjectsInScene . Now select the create object button, add the -command again and type in objectCreation . Now select the rename object button, do the same as before and type in objectRenamer in the text field this time. We are now done! You can drop both the mel file and the ui file (after you've saved it of course) and put them in your scripts folder! To see it in action, just type:

source object_creator_tutorial.mel; objectCreator();

either into the mel command line or into the script editor and run it! This is what you should see:

final_shot

I've created a few objects using it and renamed the sphere to test. Nothing fancy. Just a way to learn QT and Mel. :)

But wait! How are you going about pulling that information from those fields? Great question self! I'll go through what commands I'm using to pull the information from all of those fields. The code is commented, but again, I like being thorough.

Ok so, to name our object, I chose to use a single text field rather than using two, because of two reasons: 1) It cuts down on code; and 2) It makes it so the interface looks cleaner. Remember when we named our text fields top level name to objectNewName? Well this line right here pulls that name:

string $objectNewName = `textField -q -text objectNewName`;

Maya understands that the UI has a textField and it's name is objectNewName. The -q flag queries the data from that field with -text being the explicit data we're looking for. Note that maya treats numbers as text as well (because QT doesn't have an integer box, only text boxes), so if you need an integer from a text field, simply recast it doing something like this:

			string $textFieldData = `textField -q -text nameofTextField`;
			int $textFieldNumber = $textFieldData;
		

Sorry for the aside, but knowledge is power. :) Ok. So we got the text via that line. How are we putting stuff into the scrollList. This actually took me a few minutes to figure out because of two reasons: A) I followed someone else's documentation without trying for myself; and B) It's the only object to be Item Based. So we named our Scroll List to objectScrollList . Here's the code that's updating that list:

			//to get the meshes available
			string $listObjects[] = `ls -type mesh`;
			//get the transform node
			string $topLevelListObjects[] = `listRelatives -parent -type "transform" $listObjects`;
			//clear the scroll list so no duplicates show up
			textScrollList -e -ra objectScrollList;
			//iterate through and add all the meshes
			for($item in $topLevelListObjects){
				//update the items in the scroll list
				textScrollList -e -a $item objectScrollList;
			}
			
		

What we're doing is querying the scene for any meshes and then selecting their transform nodes rather than their shape nodes (which would be the default). Then we clear the scroll list so we don't add duplicates (just being sanitary). After that we go through each item and append it to the current list. We could add a function in here to check and see if there's any objects in the scene and if not to not bother running the function, but that'd be an extra variable and an if else statement, so that's another 6 lines of code. While it's good to add in error checking and I usually do, the script would probably run slower if it had that ability since it'd be another iteration. However, we can add that if we want to later. Again, this is more of a demo than a mel howto.

So now we know where we're getting our variables from and what commands are pulling the data. What's left? Absolutely Nothing! Now you're equipped with a better idea of how Mel, QT and Maya work together! Hopefully this was informative to you and you can get out there and write some awesome scripts using QT. If you'd like to know what other commands interface with Maya from QT you can check out this post on CreativeCrash from css_maya. He does a great job of outlining the different variables, although you will note that his list view is incorrect (which you'll also see I pointed out in his comments). He also goes through setting up a dial control to work with Maya. I'd rather use a slider, but to each his own! It's cool and you can do it so why not!

If you need any help, feel free to shoot me an email from my contact page or if you're reading this on CreativeCrash send me a pm! Have a good one and make some cool stuff! Oh and you can download the files for this tutorial here.

Comments

Dashboard_avatar
Jul 21, 2010
Post id: 11874
Report this comment to moderators [SPAM]

Thanks for this ! very very useful !
Do you have useful sources for using qt designer and maya together ?
Thanks

View John Neumann's profile
Jul 21, 2010
Post id: 11876
Report this comment to moderators [SPAM]

I'm glad you liked it! The only other resources I've found have been here: https://www.creativecrash.com/maya/tutorials/scripting/mel/c/using-qt-designer-for-mel-interfaces Aside from that it's a lot of trial and error and reading the documentation. I'll do another write up soon on how to get the drop down menus on the top to work. The way I figured it out is a bit of a hack, but it works. I'll try to get that done sometime this weekend! Glad you enjoyed it and thanks for the feedback!

View lalamax3d 's profile
Aug 10, 2010
Post id: 12107
Report this comment to moderators [SPAM]

this is amazing, coolest , to the point, nicely explained thing.
i definitely don't mind dropdown menu tutorial coming after that. but super amazing thing would be
a- publish same level task in python with pyqt
b- same level task with pymel

cheers, thanks again for efforts and helping community..

Dashboard_avatar
Aug 11, 2010
Post id: 12122
Report this comment to moderators [SPAM]

Thanks for this great Tutorial !!!
Yes, designing interfaces with QT is a breeze compared to the hard work you had to do in MEL...

This has nothing to do with the tutorial itself...
But, does anybody wonder why using intfields and/or floatfields is not explained?
One would assume that int/floatfields are accessed in the same way the objectNewName is queried from the textField... Well... Wroooong!!!

Because Maya doesn't support QT 'PROPERLY' !!!!!!!!!!!!!!!!!!!
This GINORMOUS PROBLEM makes me want to throw the whole thing outside the window.

The spin box widget and double spin box widget ARE NOT SUPPORTED... ?????
- spin box widget = intField (should be)
- double spin box = floatfield (should be (casting a double to a float isn't a problem))

Even sliders are accessible but simple int/float fields aren't????
How the hell did those at Autodesk manage to pull off such stupidity?

YES YOU CAN! They'll say... :
You can connect the spin box with an invisible textbox or slider in QT. In Maya you can access the textbox (or slider) with `textField -q -text nameOfWidget` and then cast the result string to a int or float... blablabla

What if I want to set the value of the spinbox in MAYA? And what if I want things to work in both ways (get/set = loop problem in QT).
Guess they also have an even more complicated answer ready for this too.

Are you kidding us, you Autodesk scum?!!?

Nevermind, they say, Spinboxes and DoubleSpinboxes will be supported in the future1 :) Yipeeeee.
So you all need to buy the next release too and rewrite scripts made using the workaround mentioned above.

What I'm saying is:

GETTING/SETTING VALUES OF INTS/FLOATS IN A GUI IS ONE OF THE MOST BASIC THINGS!!!!

SHAME ON YOU, AUTODESK !!! STOP SELLING US HALF WORKING PRODUCTS AND PROMISSING IT WILL WORK IF YOU BUY THE NEXT VERSION !!!!! (Imagine a carbuilder telling you that)

THIS IS CALLED THEFT!!!

View John Neumann's profile
Aug 27, 2010
Post id: 12273
Report this comment to moderators [SPAM]

Sorry for not responding sooner. I actually had responded, but apparently it never took. :/

@lalamax3d: When I wrote this, I didn't know python, but I spent a weekend to hammer it out and now I understand it and can do most things in it that I was doing in mel, but much more efficiently. So I will be making one for pyQT and pyMel in the near future (probably a few weeks or so, just so I don't put misleading info on there since I'm still new to Python). :) Thank you for the suggestions!

@ljilekor: Thank you for the compliment and I'm glad you liked the tutorial. I agree with you that the implementation could have been better and thought that maybe with one of the service packs they've released that they would have updated it and fixed the fact that there's no float/int fields available. And that's part of why I noted in the tutorial that you need to recast it. HOWEVER, that is the beauty of using Python vs Mel, because each variables type is dynamically typed, so you don't have to worry about stuff like that. Again, that's specific to Python, so it is stupid that there isn't something that would work for Mel.

Thanks for all the views everyone and rate it if you think it was helpful (or not) so I know whether I'm putting out info that's helping someone. :)

View Zhang Yu's profile
Dec 18, 2010
Post id: 13320
Report this comment to moderators [SPAM]

Thanx a lot. That's really a good tutor,it's very useful and i'm also a newer with python ,I learn a lot,if you have many other valuable tutor or ideas ,please share

Dashboard_avatar
Jan 06, 2011
Post id: 13464
Report this comment to moderators [SPAM]

Very good documented! Perfectly done, thank you for that greate introduction and as you said "knowledge is power!"

www.schiho.com

Dashboard_avatar
Jan 18, 2012
Post id: 15730
Report this comment to moderators [SPAM]

I like you. thank.

Dashboard_avatar
Feb 24, 2012
Post id: 15919
Report this comment to moderators [SPAM]

Great tutorial! Any word on doing this through python? I'm trying to rid myself of all things MEL when possible.

View John Neumann's profile
Feb 24, 2012
Post id: 15920
Report this comment to moderators [SPAM]

It has been on my to do list for quite some time. The biggest problem is that when you move to Python you ultimately have to rid yourself of the designer and utilize straight PyQt, which then means that you're getting into some much heavier stuff. Ultimately it ends up becoming much more about using PyQt and writing interfaces for it than it is about using Qt Designer to make things simple. So while it's something I'd like to do, I don't know that I'm going to be doing it anytime soon.

However, you can check out Nathan Horne's site: http://nathanhorne.com/?p=451 for a PyQt/PySide tutorial that's really well done.

And I agree that anything that I have that's in Mel I puke all over now. Every time I have to open up one of those freaking mel files I cry inside and curse out loud. :)

Dashboard_avatar
Dec 25, 2013
Post id: 18973
Report this comment to moderators [SPAM]

thank you... for sharing information... how to apply MEL code on Qt List View :)

Write a Comment

You must be logged in and have verified your email address to leave a comment. Login or create an account