Lesson 3: More building interfaces

I always find something quite satisfying about building an interface, the only issue is it can be quite quick to build something that looks good and has amazing intentions but can then take a long time to make it all work, difficult to justify to your boss sometimes if you’ve got a button which doesn’t do anything.  Lets build an interface with lots of different UI controls and see how we interact with all of them.

try(DestroyDialog RL_UiTest)catch()
rollout RL_UiTest "UI Test"
(
    label lbl_A "Label A"
     button btn_A "Button A"
     checkbox chk_A "Checkbox A"
     spinner spn_A "Spinner A" range:[0,10,1] type:#integer
     dropdownlist ddl_A "Dropdownlist" items:#("item1","item2","item3")
     listbox lbx_A "Listbox A" items:#("item1","item2","item3")
     edittext edt_A "Edit Text A"
     radiobuttons rdo_A "Radiobuttons" labels:#("Option 1", "Option 2")
)
Createdialog RL_UiTest

Give that a try and you’ll get a useless interface full of things that do nothing, it took me a while to get my head around how to work with all these interface items so lets go through a quick guide to how to interact with them.

I’ve only specified the basic initial parameters in this example, some of the controls have additional parameters beyond, pos, height and width, look at the maxscript help for more examples. All controls are defaulted to enabled:true on creation but you can override that if you want your control disabled by setting it to enabled:false as an initial parameter.

Lets look at the format for defining UI controls.

ControlType Name Caption [parameters]

ControlType is the thing which tells maxscript which control we want, the Name can be anything you like but it makes sense to have some consistent naming conventions throughout all the scripts you write so it’s easy to reference the controls. I always try to make sure there is an obvious connection between the caption that you see in the interface and the name on the control, certainly makes things easier to debug when you come back to a script after months away from it. For example, if you have a button with a caption of “Cancel” it makes more sense  to call that button btn_cancel rather than btn_1.

label lbl_A "Label A"

We can change the text of the label by changing the caption property to a new string (think text) value. Most UI controls have caption properties.

lbl_A.caption = "New Caption"

There are no events for labels, this means you can’t expect to have a user click or right click on a label and expect anything to happen. You can make a button with no border which would look like a label.

button btn_A "Button A"

Additional parameters are tooltip (which goes for most, but not all controls) border (see above) and images array, which is for if you want to make a button with an image icon. It’s not quite as simple as specifying one image, as the button expects an array of arguments which tell it more than what image to use, but also if it needs a mask etc… see the maxscript help for more on this.

The events for the button control is as you might expect, pressed, and also rightclick. Pressed will depress the button whereas rightclick won’t make the button look pressed, it’s quite common to use the rightclick event to create a popup menu called an RCMenu (we’ll make one of those another day).

on btn_A pressed do
(
    print "btn_A was pressed"
) 
on btn_A rightclick do
(
    print "btn_A was rightclicked"
)
checkbox chk_A "Checkbox A

The checkbox is used for letting the user set a value to “yes” or “no”, or as you’re now a coder you need to think… true or false,  you can set an additional parameter when creating the checkbox for setting the state of the checkbox. Note were using a : colon, not a . here as we’re specifying a creation parameter not changing a property.

 checkbox chk_A "Checkbox A" checked:true

If we look at the event for a checkbox, there is just one which is called when the checkbox state is changed by either being ticked or unticked, there’s an additional argument in our event which tells us what the state of the checkbox is.

on chk_A changed state do
(
    print ("the state of the checkbox is:" + state as string)
) 

spinner spn_A "Spinner A" range:[0,10,1] type:#integer

The spinner control has some initial parameters, with a spinner we have to define the range of what the spinner can scroll up and down to and its initial value. range:[lowest value, highest, initial] and also the type of the value in the spinner which can be a #integer (whole number), #float (decimal numbers) and #worldunits (measurements), it’s important to use the right type or you’ll have issues with your scripts, if you try to set a turbsmooth iteration value via a spinner control to 2.5 then your script is going to throw and error so make sure it’s set to #integer for that. The default type is #float. It’s good to use a spinner control wherever you want the user to enter a number value into your script, if you give them an edittext box (see later) then the user could enter any type of number or a letter just to confuse your script.

You can link a spinner to a controller of a value on a max node by specifying the controller parameter with a node controller:($Sphere001.radius.controller)

If you want to get the value of the spinner you can access the .value property ie. spn_A.value or if you wanted to set the value once the script is running, spn_A.value = 10

There are a few events for the spinner control but I only use the changed event, in most cases this will do what you want, but refer to the maxscript help for the additional events.

on spn_a changed val do
(
    print ("the value is:" + val as string)
)

If you  were wanting to write a script which say.. created a number of spheres, and you wanted a spinner to control the number, it wouldn’t be a good idea to have the creation of the spheres in the on spinner changed event, as every time you scrubbed the spinner it would create lots! Better is just to use the spinner to set a number, it wouldn’t need an on changed event, and then have a separate button which looks at the value property of the spinner.

dropdownlist ddl_A "Dropdownlist" items:#("item1","item2","item3")

A dropdownlist needs a list (or array as we should be calling it) of items to display in it. We’ve talked about arrays before but this is the first time we’ve written our own array, the #() signifies an empty array, an array can have any number of items inside it, and they can be of different types, be sure to remember to put quotations around any string values. #(“Test1”,1,true, 1.0) would be a valid array. For dropdownlists it needs an array of only string values, or it’ll kick up a fuss, it’s a good idea not to have too many items in a dropdownlist, if you need lots it’s probably better to use a listbox instead which will have a scroll bar.

The properties we can access are items, which gives or sets our array list for the dropdownlist. We can get .selection which will give us the number of the selected item in our array list and the .selected will give us the actual text (string) of the selected item, ie “item1” . I always get confused between these two and more often than not get it the wrong way around!

The event for handling when the selection changes is as follows…on ddl_A selected sel do the argument sel is the index number of the selected item, the same as .selection property.

on ddl_A selected sel do
(
    print ("The selection number was:" + sel as string)
    print ("The selected text was:" + ddl_A.selected)
) 

listbox lbx_A "Listbox A" items:#("item1","item2","item3")

The listbox is very similar to the dropdownlist so I won’t go through all of that again, a standard listbox can only select one item at a time, if you want more control and things like checkboxes then you’re looking at getting into dotnet, google “PEN dotnet tutorial” and be ready to be confused by dotnet.

The additional event for the listbox is doubleclicked, which as the selected returns the item index.

on lbx_A doubleclicked sel do
(
    print ("The selection number was:" + sel as string)
    print ("The selection number was:" + lbx_A.selection as string)
    print ("The selected text was:" + lbx_A.selected)
) 

edittext edt_A "Edit Text A"

EditText boxes are simple text entry boxes, there’s a really important thing to know with EditText and it’s height, if the height is 18 pixels or more, it will be treated as a multi-line text box and the event handling changes.

We can set the text parameter to give us initial text in the box if we like text:”this is not a fish” and of course (hopefully you’re guessing this by now) you can set text by the .text property, edt_A.text = “This is a fish”

The events are on changed, and on entered, the difference is any change made by typing in the box and entered is when the ENTER key is pressed or when the editbox loses focus, ie when you click on another UI item or press TAB. If you’ve got a multilined text box then the on entered event will only happen when the focus changes and not when you put a carriage return in by pressing ENTER. The text argument will return a string value of course.

on edt_A changed text do
(
    print ("edt_A text is:" + text) 
)

on edt_A entered text do
(
    print ("edt_A text entered was:" + text)
)
radiobuttons rdo_A "Radiobuttons" labels:#("Option 1", "Option 2")

Finally the radiobutton, useful for giving the user options with all options laid out in view. Radiobuttons needs an array of labels, which like items for the listbox is an array of strings. Additional parameters are default, for setting the default selection, default:2 and columns for laying out neatly into columns… columns:2

You can find out what the radiobutton is set to by getting/setting the state property which will give you a number of the selected radiobutton.

You can set the state to 0 to make none of the options selected.

The events is much like the checkbox, on changed event.

on rdo_A changed state do
(
    print ("rdo_A state is:" + state as string)
)

So lets put that all into a final script, give it a run and then open the maxscript listener… Maxscript-> Maxscript-listener and see the print command outputting to the listener.

try(DestroyDialog RL_UiTest)catch()
rollout RL_UiTest "UI Test"
(
     label lbl_A "Label A"
     button btn_A "Button A"
     checkbox chk_A "Checkbox A" checked:true
     spinner spn_A "Spinner A" range:[0,10,1] type:#integer
     dropdownlist ddl_A "Dropdownlist" items:#("item1","item2","item3")
     listbox lbx_A "Listbox A" items:#("item1","item2","item3")
     edittext edt_A "Edit Text A" text:"this is not a fish"
    radiobuttons rdo_A "Radiobuttons" labels:#("Option 1", "Option 2")

     on btn_A pressed do
    (
        print "btn_A was pressed"
    )
    on btn_A rightclick do
    (
        print "btn_A was rightclicked"
    )

    on chk_A changed state do
    (
        print ("the state of the checkbox is:" + state as string)
    ) 

    on spn_a changed val do
    (
        print ("the value is:" + val as string)
     ) 

     on ddl_A selected sel do
     (
        print ("The selection number was:" + sel as string)
        print ("The selected text was:" + ddl_A.selected)
    ) 

    on lbx_A selected sel do
    (
        print ("The selection number was:" + sel as string)
        print ("The selection number was:" + lbx_A.selection as string)
        print ("The selected text was:" + lbx_A.selected)
    )
    on edt_A changed text do
    (
         print ("edt_A text is:" + text) 
    )

    on edt_A entered text do
    (
        print ("edt_A text entered was:" + text)
    ) 

     on rdo_A changed state do
    (
         print ("rdo_A state is:" + state as string)
    ) 
)
Createdialog RL_UiTest
Advertisements

About davewortley

Somewhere between an artist and a programmer, I like technical things, but being creative. I love problem solving and coming up with elaborate solutions. This blog is where I shall share ideas, tips, tutorials and anything that amuses me.
This entry was posted in Lessons, MaxScript. Bookmark the permalink.

3 Responses to Lesson 3: More building interfaces

  1. Gerald says:

    Hi Dave
    I really like the blog so far. Very interesting articles and also well explained.
    Keep up the good work 🙂

    Like

  2. Gabe says:

    I was stuck on the listbox and this got me past it, so thank you.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s