Houdini 20.5 Python scripting hou hou.qt

hou.qt.ListEditor class

A convenient user interface (as a dialog or a reusable widget) for displaying/editing a list of strings.

On this page

Overview

Often when designing a user interface, you need provide the user with a way to view/edit a list of strings. For example, configuring a list of directories to search for plugin files, or a list of tags to apply to an object, or a list of object paths that a light should illuminate.

This object provides a compact, simple, yet powerful editor for these types of jobs. You provide a list of strings to present to the user. The widget allows the user to add, delete, reorder, and/or edit items in the list (depending on the options).

In addition to editing the text of the strings, you can display checkboxes next to each item, and use the checked state as additional information. For example, you might have an interface where the user specifies a list of asset libraries to pull props from. You can provide checkboxes on the items to let the user temporarily enable/disable individual libraries without having to delete and re-add them.

Using the hou.qt.ListEditorDialog convenience class

To get a ListEditor in a dialog window, you can use the pre-made class hou.qt.ListEditorDialog. It takes the same keyword arguments as ListEditor and simply wraps the widget in a dialog window.

Use the ListEditorDialog.editor() to get a reference to the `ListEditor

This class inherits from Qt’s QtWidgets.QDialog class. Refer to the Qt documentation for information on the large number of useful methods provided by this object.

Non-modal dialog

  1. Instantiate and configure the widget with the options you want.

  2. Connect to the widget’s accepted, rejected, or finished signals.

  3. Call .show() on the dialog object to open it as a window.

def show_tag_editor_for(node):
    # Create and configure the editor widget
    dialog = hou.qt.ListEditorDialog(allow_editing=False, allow_add_remove=True,
                                     allow_reorder=False, keep_sorted=True,
                                     show_checkboxes=True, initial_check=False)
    dialog.setWindowTitle("Edit Tags")

    editor = dialog.editor()
    editor.setTopMessage("Check the tags you want to apply. You can add new tags.")

    # Set the contents of the editor to the list of all known tags. Check the tags
    # that currently apply to the given node.
    for tag in list_of_all_tags:
        editor.addListItem(tag, node.hasTag(tag))

    # Connect the editor's "accepted" signal to a function that updates the tags
    dialog.accepted.connect(lambda: update_node_tags(node, editor.stringsAndChecks()))

    # Stash a reference to this widget in `hou.session`, so it doesn't go away as soon
    # as this function ends. This is a bit simplified, since storing it in a variable
    # like this means there can only be one tag editor at a a time.
    hou.sesssion.tag_editor = editor

    # Show the widget as a window so the user can interact with it
    dialog.show()


def update_node_tags(node, tags_and_checks):
    for tag, checked in tags_and_checks:
        if checked:
            node.addTag(tag)

Note

Remember that you must have at least one persistent reference to the widget, otherwise the window will be garbage collected and immediately close.

Embedding ListEditor as a widget in a Qt layout

You can use ListEditor as a plain widget in a larger user interface.

  1. Instantiate and configure the widget with the options you want.

  2. Add the widget to a Qt interface as you would with any QWidget.

  3. Use the widget’s strings() or stringsAndChecks() methods when you need to get the current editor contents.

# Set setting up your Qt user interface
class MyUI(QtWidgets.QFrame):
    def __init__(self, parent):
        super(MyUI, self).__init__(parent)
        layout = QtWidgets.QVBoxLayout()
        self.setLayout(layout)

        # Create and configure the ListEditor object
        self._editor = hou.qt.ListEditor(allow_editing=True,
                                         allow_add_remove=True,
                                         allow_reorder=True,
                                         allow_empty_string=False)
        self._editor.setTopMessage("Add, remove, or edit which files to read")
        # Get the current list of file paths from a variable
        self._editor.setStrings(list_of_file_paths)

        # Add the widget to your user interface
        layout.addWidget(self._editor)

    def read_files(self):
        for filepath in self._editor.strings():
            ...

Tips and notes

  • When allow_add_remove=True but allow_editing=False, the user can type out the initial string value of a newly created item, but cannot then edit that string after pressing Enter.

  • If you have allow_reorder=True and also keep_sorted=True, the user will be allowed to drag items but dropping them will not change the order. To prevent confusion, you should turn off allow_reorder if you turn on keep_sorted.

Signals

itemEdited(int, str)

Triggered when the text of an item is changed. Called with the row number (starting at 0) and new text of the item.

checkChanged(int, str, bool)

Triggered when the check state of an item is changed. Called with the row number (starting at 0), the text of the item, and the new checked state (True or False).

listChanged()

Triggered anytime the list of strings changes (the user adds, moves, or removes items). You can then call the strings() or stringsAndChecks() method to get the new list contents.

Methods

hou.qt