Part 2: Connecting UI elements!
Now that we can use a .ui file in Maya, we need to add functionality! We can connect buttons, connect sliders with text displays and input fields, and update UI elements dynamically! The demo files for this post may be found at the very end.
The base Python file / UI:
These are the files I am starting from / using in this demo, a sample UI .ui file, and the basic python file from part 1:
A neat aspect about the .ui file is that if you don't set the palette colors in QT Designer to be dark grey, Maya will color it appropriately as seen above. The only custom set color is the blue button.
This is my base python file from part 1, beyond changing a few lines, the rest of the code is the same.
The most basic of operations, we want to do something when a button is pressed. Generally, I either connect my buttons within the __init__ of the class, or, if I have a multi-page UI, within the function that shows the widget containing the buttons / UI element.
The first part of connecting a button is the line to connect the UI element to a command.
self.MainWindowUI - this is the reference to our UI object within the class
BTN_hi - this is the objectName of our button ( QPushButton ) from QT Designer
clicked - this is the signal that we want to capture: whenever the button is clicked
connect( . . . ) - connect what ever is within the parenthesis to the object's signal
lambda: - prefix any function with this, otherwise Python won't be happy with you!
self.printHello() - the class function we want to call when the button is pressed
The second part, our actual function that we're calling - nothing fancy here, it can be a class function or a global function located elsewhere.
Connecting a Slider to a text / LCD display:
So this is where I show my little secret on QT signals, I'm horrible about memorizing them all and I hate looking them up in the QT documentation ~ fortunately for us, QT Designer will tell you what signals exist for a given object:
If you show the Signal / Slot Editor, press the green plus sign and select the desired object as your 'Sender' node, the signal drop-down lists the name of every available signal. For our purposes, we could use sliderReleased, sliderMoved or even valueChanged.
Next up, I just need the appropriate function - I want to get the value of my slider, and feed it into the display object. When dealing with the specifics such as this, I often find myself referencing the online QT documentation.
When I move the slider, it will update the LCD display widget in real time, and only print out the value when I let go of the slider. Often times, we'll want to give immediate UI feedback to the user, but not actually do anything with the data until they let go.
Connecting a Text box to a Slider:
In quality UIs, we want the flexibility of modifying an attribute by using the slider OR the text box, this is where things get more fun - it's the same process to have the slider influence the text box, however we have to do a lot of quality checking before we can use the text box to set the slider, and a fail-safe if the user's input is invalid or out of range:
This function can be broken up into the following sections:
Lines 3 - 5: We are collecting the user's input, and the slider's valid range.
Lines 7 - 12: Make sure the user's input is a valid integer, if not reset it using the slider's value, tell the user about their error and then end the function
Lines 14 - 18: Now that we know the value is an integer, clamp it to the valid range of the slider, update the slider's value, update the textbox to the clamped value, and then print this data out for the user to see.
Allowing math input:
Something really cool that we can do is to allow the user to input a math expression such as "5*2" , and it's actually not difficult to do, requiring only a few changes:
In the top of the file, we'll need one more import, mel.eval, which I usually import as:
and we're going to change the try / catch block in our function to:
Now the user can enter basic math functions as though it were a calculator and it will work. It will still throw errors here and there for syntax errors generally, but it won't yell at the user - instead it should just roll the value back.
Wrapping it up!
using a .ui file, it is rather simple to connect buttons, sliders and other widgets together, as well as obtain data and use it to update other UI elements. We can use QT Designer to quickly tell us all of the available signals for any widget, or look up the QT online documentation for the available commands. And, as an added bonus, it's relatively easy to get some basic calculator functionality into there as well!
Demo Files ( .zip )
To use the demo files:
1) Close Maya if it's open
2) Extract the contents of this.zip into your maya/scripts/ folder
3) Open Maya
4) in Maya, create a python shelf script with the following code:
Press the shelf icon and it should open up!