Traits UI IntegrationΒΆ

The Bound class is a Traits UI Item that can be used to place a Binder widget into a Traits UI View and bind it to traits on the model or Handler. It comes with its own Editor that knows how to set up the Binder and use it as the control for the Item.

The Bound constructor takes a Binder instance and some bindings. Bindings are either instances of Binding subclasses or, more conveniently, specially-formatted strings that will be parsed to Binding subclass instances.

traits_view = View(
    Bound(
        HBoxLayout(
            Label(id='label'),
            LineEdit(id='edit', placeholderText=u'An integer'),
        ),
        Factory('edit.validator', QtGui.QIntValidator),
        'label.text << handler.label',
        'edit.text := object.text',
        'spacing = 5',
    ),
)

This example View succinctly demonstrates most of the Traits UI features. The HBoxLayout is a Binder that transparently wraps the QHBoxLayout Qt layout object. It is slightly customized with a constructor that lets you declare the child widgets by passing Binder objects. Thus you can build most typical layouts using a hierarchy of layout and widget Binder objects. Binder constructors can take an id keyword argument that sets a name for the Binder that should be unique to the tree of Binder objects it is in. This name will be used to refer to that Binder in the bindings that follow. Other traits that proxy Qt properties can also be set in the Binder constructor. They will be assigned when the underlying QObject is assigned to the Binder.

Following the root Binder is a list of Binding strings or objects. These follow a pattern of 'binder_trait <operator> model_trait_or_expression'. On the left of the operator is either the name of a trait on the root Binder (e.g. spacing refers to the HBoxLayout.spacing property) or a dotted reference to a trait on a descendant Binder that has provided an explicit id (e.g. edit.text refers to the LineEdit.text property).

On the right side of the operator is an expression evaluated in the Traits UI context. For a Binding that writes back to the model (:=/SyncedWith and >>/PushedTo), this is restricted to a simple extended trait reference; i.e. object.foo.bar but not object.foo.bar + 10. This context starts with the Traits UI context (i.e. has object and handler at a minimum) and is extended with any Binder in the tree with a non-empty id. For <</PulledFrom, the expression will be parsed for extended trait references and the binding will be evaluated whenever it changes. For example, format(handler.template, object.child.value) will re-evaluate and assign to the left-hand side whenever handler.template OR object.child.value changes.

Note

Annoyingly, at the moment we cannot detect when such a dotted reference has a non-terminal non-HasTraits object. In the example above, handler.template.format(object.child.value) would cause an error because handler.template is a string, not a HasTraits object to which a listener can be attached.

There are four operators that can be used in the string representations of Binding objects:

  • = or SetOnceTo: Set a value once. This evaluates the right-hand side once when the binding is established. No notifications will be sent afterwards.
  • << or PulledFrom: Pull values from the model. This evaluates the right-hand side once when the binding is established and whenever any traits used in the expression fire a change notification.
  • >> or PushedTo: Push values from the Binder to the model. When the Binder trait on the left-hand side changes, this will assign the new value to the attribute referenced on the right-hand side. No value is assigned on initialization.
  • := or SyncedWith: A combination of PulledFrom and PushedTo to synchronize a binder trait with a model trait. Because the right-hand side of PushedTo is restricted to plain attribute references, so is this. Like PulledFrom, the right-hand side will be evaluated when the binding is established and assigned to the left-hand side to initialize it.

And the last Binding cannot be put into string form:

  • Factory: Call the provided function once when the binding is established, and set the value. No notifications will be sent afterwards.

Bindings which initialize a value (i.e. SetOnceTo/=, PulledFrom/<<, SyncedWith/:=, and Factory) will be evaluated in the order in which they are specified. This can be important for initializing some Qt objects. For example, setting up validator properties before assigning the value.

Bound takes the following optional keyword arguments:

label : unicode
Like the normal Item label argument, except that if one is not provided, then Bound will set show_label=False. Since the Bound Item is not exclusively associated with any single trait like other Traits UI Items are, the default Traits UI behavior of using the trait name as a label is not useful.
extra_context : dict
Any extra objects that should be added to the context used to evaluate the right-hand-side of bindings.
configure : function with signature configure(binder, context)
A function to call after the root Binder has been constructed and the bindings established but before display. It will be passed the root Binder and the context dictionary. This can be used to do customizations using the raw Qt API that may not be achievable using bindings alone.
stylesheet : unicode
A Qt stylesheet applied to the root control.
button_groups : dict naming ButtonGroup objects
Collect buttons in the UI into named, bindable groups that will be added to the context.

Previous topic

Core Principles

Next topic

To Do

This Page