-
Notifications
You must be signed in to change notification settings - Fork 23
Tutorial 3: Forms
This tutorial assumes you've gone through the first and second tutorials already
One of the most tedious and time-consuming parts of laying out a gui in Maya is managing the overall structure of a window or layout. The basic layout commands like ColumnLayout
and RowLayout
are clunky and don't handle resizable elements very well. Maya also provides a much more powerful tool in formLayouts -- but unfortunately the syntax for them is mind-numbing.
mGui supports the formLayout
command as the FormLayout
class, using the same syntax as other mGui classes. However a much easier set of tools is available in the module mGui.forms
. This module makes it much simpler to layout your gui so that it responds properly when users resize windows or panels.
For an overview of all the classes in mGui.forms, see the forms page.
The big advantage of forms is that they handle resizing properly. If you stick with ColumnLayout and RowLayout, for example, it's hard to make even something as simple as a column of checkboxes with followed by an 'accept' and a 'cancel' button which will properly resize:
---------------
| [] check |
| [] check |
| [yes] [no] |
---------------
in mGui, this would look like this:
from mGui.gui import *
from mGui.forms import *
with Window() as window:
with FooterForm() as main:
with VerticalForm() as checkboxes:
one = CheckBox(label = 'one')
two = CheckBox(label = 'two')
with HorizontalStretchForm() as footer:
yes = Button('yes', width = 60)
no = Button('no', width = 60)
Here's what's happening in this example:
- the
FooterForm
creates a form which has two children. The first one is expandable, the bottom one will stick to the bottom of the window. - the first child of the footer is a
VerticalForm
, which is similar to a columnLayout except that its children will resize horizontally as it scales. - in that Vertical form we make two checkboxes
- the
HorizontalStretchForm
is the second child of theFooterForm
created in step 1 (you can easily see this from the indents, which are very useful for understanding the structure). Because it's the footer of the FooterForm, it will move and expand with the bottom of the window. And because it's a HorizontalStretchForm(), its children will both stretch to handle expansion in the horizontal direction.
Another big advantage of the forms classes is that they make it relatively easy to handle the spacing and layout of the forms themselves. Instead of trying to lay out your controls with manual placement options, nested forms can make it easy to achieve a neat, consistent layout that also works with resizable windows.
If you ran the example above you'll notice that the checkboxes are very snug against the left-hand margin of the window, which does not look very nice. mGui includes a robust set of tools for managing graphic styles in the mGui.styles module. We can use the margin
and spacing
features of the CSS
class to make get those checkboxes into a more attractive location.
Here's the same example, with the addition of CSS to handle the spacing of the checkboxes
from mGui.gui import *
from mGui.forms import *
from mGui.styles import CSS
padding = CSS(None, margin = (24,12))
with Window() as window:
with FooterForm() as main:
with VerticalForm(css=padding) as checkboxes:
one = CheckBox(label = 'one')
two = CheckBox(label = 'two')
with HorizontalStretchForm() as footer:
yes = Button('yes', width = 60)
no = Button('no', width = 60)
When you run this the VerticalForm containing the checkboxes has a 24 pixel margin on the sides and a 12 pixel margin at the top, which is much more readable.
The CSS class also allows you to specify the spacing between objects in forms. You'll notice that the 'yes' and 'no' buttons are right up against each other. We can fix that with a CSS like this:
padding = CSS(None, margin = (24,12))
btns = CSS(None, margin = (8,8), spacing = (4,0))
with Window() as window:
with FooterForm() as main:
with VerticalForm(css=padding) as checkboxes:
one = CheckBox(label = 'one')
two = CheckBox(label = 'two')
with HorizontalStretchForm( css = btns) as footer:
yes = Button('yes', width = 60)
no = Button('no', width = 60)
Now the buttons have an 8-pixel margin between them and the window and an 8-pixel buffer (because there are two 4-pixel spacings) in between them. By consistent use of forms and CSS objects you can keep your guis neat with a minimum of effort -- and keep the visual style information disentangled from the logical structure of the gui.