TraitsUI 8.0.0

repository·main·Indexed 43 days ago

https://github.com/enthought/traitsui

A toolkit-independent GUI abstraction layer for creating user interfaces for Traits-based models. It decouples data models from specific GUI toolkits like Qt or Wx and provides a wide range of standard and advanced editors, including TreeEditor and TabularEditor. Includes a toolkit-agnostic testing API via traitsui.testing for writing self-checking tests using UITester, UIWrapper, and TargetRegistry.

Tokens
40.9K
Snippets
100
Records
178
Agent score
54%

What's inside TraitsUI

  1. Overview of Predefined Trait Editor Factories

    main

    TraitsUI provides a set of predefined trait editor factories to automatically generate user interfaces for editing traits. These factories are categorized into two main groups:

    1. Basic Trait Editor Factories: Straightforward editors that are easy to use with little to no specialized expertise.
    2. Advanced Trait Editors: Specialized editors with more complex interfaces or those designed to work alongside complex editors.

    Note on Toolkits: The visual appearance of these editors depends on the underlying GUI toolkit being used (e.g., Qt or wx). Documentation and screenshots may reflect a mix of both.

  2. Testing TraitsUI Applications

    main

    TraitsUI provides a toolkit and an independent API designed to help developers verify the behavior of their applications through automated tests. Most testing functionality is centralized in the traitsui.testing module.

    Note that the testing library is a newer feature compared to other parts of TraitsUI, and built-in support for testing TraitsUI editors is actively being expanded.

  3. What is TraitsUI and how does it work?

    main

    TraitsUI is a toolkit-independent GUI abstraction layer designed to support the visualization features of the traits package.

    It allows you to separate your data model from your user interface:

    1. Model: Define your data using the traits API (e.g., HasTraits).
    2. View: Specify the GUI using the TraitsUI API (defining Views, Items, and editors).
    3. Backend: TraitsUI uses a selected toolkit backend (such as Qt or Wx) to handle the actual rendering and windowing details.

    This abstraction means you can write your logic once and swap the underlying GUI toolkit without changing your model or view definitions.

  4. Overview of the TabularEditor

    main

    The TabularEditor is a high-performance, flexible editor located in the traitsui.wx.extras.tabular_editor module. It is designed for large datasets using a virtual model, meaning it only accesses data from the underlying model as needed (e.g., requesting only the visible 50 rows of a million-row array).

    Key Strengths

    • Performance: Extremely fast due to the virtual model.
    • Flexibility: Uses an adapter model to interface with various data formats (lists of objects, arrays, tuples, etc.).
    • Built-in Operations: Supports keyboard navigation, row insertion/deletion, and drag-and-drop (copy and move).
    • Visuals: Uses native OS table/grid controls and supports displaying text and images in cells.

    Limitations

    • Features: Lacks some advanced filtering, searching, and sorting capabilities found in the older TableEditor.
    • Editing: Currently limited to editing textual values due to native OS control constraints.
  5. Define External Views

    main

    External Views are defined outside of the model classes. This follows the MVC pattern by separating the data (model) from the presentation (view). You can define a view as a module-level variable, or even inline as an argument to a method.

    from traitsui.api import View, Group, Item
    
    # External view defined as a variable
    my_external_view = View(
        Group(
            Item(name='a'),
            Item(name='b'),
        )
    )
    
    # Using an inline view directly in a method call
    model.configure_traits(
        view=View(
            Group(
                Item(name='a'),
                Item(name='b'),
                Item(name='c'),
            ),
        ),
    )
  6. React to specific trait changes using UI notification methods

    main

    While setattr() catches all trait changes, you can implement specific "user interface notification" methods to react only to changes in particular traits. This follows the MVC pattern by keeping UI-specific logic out of the model.

    Naming Convention: Methods must follow the pattern: {context_key}_{trait_name}_changed(info).

    • If the context key is object and the trait is salary, the method is object_salary_changed(info).
    • If the context key is h2 and the trait is price, the method is h2_price_changed(info).

    Handling Initialization: These methods are called when the window is first created. To distinguish between the initial creation and subsequent user edits, check the initialized attribute of the info object.

    def object_foo_changed(self, info):
        if not info.initialized:
            # Code executed only when the window is created
        else:
            # Code executed when 'foo' changes after initialization
        
        # Code executed in both cases
    def object_foo_changed(self, info):
        if not info.initialized:
            # code to be executed only when the window is created
        else:
            # code to be executed only when 'foo' changes after window initialization
        # code to be executed in either case
  7. How reactive programming works in TraitsUI

    main

    TraitsUI follows a reactive programming pattern where objects react to changes made to their attributes. Instead of manually updating UI widgets, you define how an object should behave when its attributes change.

    There are two primary ways to handle reactivity:

    1. Attribute Changes: To respond to an attribute foo being modified, define a method named _foo_changed(). This method is automatically called by the framework when the value of foo changes.
    2. Button Events: To respond to a user clicking a button, use a Button trait. The callback for a button named foo is defined as _foo_fired().

    This pattern allows you to build complex interactive applications by focusing on the state of your objects rather than the individual widgets.

    # Example: Reacting to an attribute change
    class EchoBox(HasTraits):
        input = Str()
        output = Str()
    
        def _input_changed(self):
            self.output = self.input
    
    # Example: Reacting to a button click
    class InteractiveApp(HasTraits):
        add_one = Button()
    
        def _add_one_fired(self):
            # Logic to execute when button is clicked
            pass
  8. Construct UI layouts with View, Group, and Item

    main

    TraitsUI uses a hierarchical structure to define user interfaces. All these components inherit from the ViewElement class:

    • View: A template for constructing a GUI window or panel. Its structure is defined by Group or Item objects.
    • Group: An object that specifies an ordered set of Items and other Groups for display. You can configure display options like borders, group labels, and element orientation.
    • Item: A non-subdividable element of a View, typically used to specify display options for a single trait attribute.
  9. Filter and search items in a TableEditor

    main

    To help users manage long lists, TableEditor supports filtering and searching.

    Filtering

    • Single Filter: Use the filter parameter to apply a TableFilter instance (or subclass like EvalTableFilter, RuleTableFilter, or MenuTableFilter) immediately upon display.
    • Filter by Name: Use filter_name to reference a trait that is either a TableFilter object or a callable (returning True for matches).
    • Filter Drop-down: Use the filters parameter to provide a list of available TableFilter objects. This adds a drop-down menu to the toolbar. A Customize option is always provided for users to manage filters.

    Searching

    • Search Dialog: Set the search parameter to a TableFilter instance. This adds a Search table icon to the toolbar, which opens a dialog for specifying criteria and browsing matches.
  10. Control GUI layout using a View object

    main

    To control the layout, appearance, and content of a TraitsUI window or panel, you must define a View object. A View acts as a template that specifies which attributes are displayed, their order, and how they are grouped.

    You can pass a View object to the configure_traits() method to override the default alphabetical display. This allows you to:

    • Show only a subset of attributes (e.g., hiding confidential fields).
    • Specify a custom order for the fields.
    • Use Group or Item objects within the View definition to structure the interface.
    # Example of passing a View object to configure_traits()
    # Note: The actual View definition is in the referenced file configure_traits_view.py
    sam.configure_traits(view=my_view_object)
  11. Understand the TraitsUI MVC architecture

    main

    TraitsUI follows the Model-View-Controller (MVC) design pattern to manage interactive applications:

    • Model: The set of classes and objects defining the underlying data and non-GUI methods.
    • View: The visual component of the application. In TraitsUI, a View is a template object constructed using Group or Item objects to define the GUI structure (height, width, menus, buttons).
    • Controller: The element that manages information transfer between the Model and the View. In TraitsUI, a Handler instance (a subclass of TraitsUI.Handler) implements this role, managing GUI logic and data manipulation.

    Common window behaviors include:

    • Live: A window linked directly to the model; changes in the UI reflect immediately in the model.
    • Modal: A window that suspends the rest of the application until it is closed.
    • Livemodal: A window that is both live and modal.