Skip to content

Gtk.ListBox

class — extends Widget, Accessible, Buildable, ConstraintTarget

Shows a vertical list.

<picture> <source srcset="list-box-dark.png" media="(prefers-color-scheme: dark)"> <img alt="An example GtkListBox" src="list-box.png"> </picture>

A GtkListBox only contains GtkListBoxRow children. These rows can by dynamically sorted and filtered, and headers can be added dynamically depending on the row content. It also allows keyboard and mouse navigation and selection like a typical list.

Using GtkListBox is often an alternative to GtkTreeView, especially when the list contents has a more complicated layout than what is allowed by a GtkCellRenderer, or when the contents is interactive (i.e. has a button in it).

Although a GtkListBox must have only GtkListBoxRow children, you can add any kind of widget to it via ListBox.prepend, ListBox.append and ListBox.insert and a GtkListBoxRow widget will automatically be inserted between the list and the widget.

GtkListBoxRows can be marked as activatable or selectable. If a row is activatable, ListBox.row-activated will be emitted for it when the user tries to activate it. If it is selectable, the row will be marked as selected when the user tries to select it.

GtkListBox as GtkBuildable

The GtkListBox implementation of the GtkBuildable interface supports setting a child as the placeholder by specifying “placeholder” as the “type” attribute of a <child> element. See ListBox.set_placeholder for info.

Shortcuts and Gestures

The following signals have default keybindings:

CSS nodes

list[.separators][.rich-list][.navigation-sidebar][.boxed-list]
╰── row[.activatable]

GtkListBox uses a single CSS node named list. It may carry the .separators style class, when the ListBox.show-separators property is set. Each GtkListBoxRow uses a single CSS node named row. The row nodes get the .activatable style class added when appropriate.

It may also carry the .boxed-list style class. In this case, the list will be automatically surrounded by a frame and have separators.

The main list node may also carry style classes to select the style of list presentation: .rich-list, .navigation-sidebar or .data-table.

Accessibility

GtkListBox uses the AccessibleRole.list role and GtkListBoxRow uses the AccessibleRole.list_item role.

Constructors

new

@classmethod
def new(cls) -> Widget

Creates a new GtkListBox container.

Methods

append

def append(self, child: Widget) -> None

Append a widget to the list.

If a sort function is set, the widget will actually be inserted at the calculated position.

Parameters:

  • child — the GtkWidget to add

bind_model

def bind_model(self, model: Gio.ListModel | None = ..., create_widget_func: ListBoxCreateWidgetFunc | None = ...) -> None

Binds model to box.

If box was already bound to a model, that previous binding is destroyed.

The contents of box are cleared and then filled with widgets that represent items from model. box is updated whenever model changes. If model is None, box is left empty.

It is undefined to add or remove widgets directly (for example, with ListBox.insert) while box is bound to a model.

Note that using a model is incompatible with the filtering and sorting functionality in GtkListBox. When using a model, filtering and sorting should be implemented by the model.

Parameters:

  • model — the GListModel to be bound to box
  • create_widget_func — a function that creates widgets for items or None in case you also passed None as model

drag_highlight_row

def drag_highlight_row(self, row: ListBoxRow) -> None

Add a drag highlight to a row.

This is a helper function for implementing DnD onto a GtkListBox. The passed in row will be highlighted by setting the StateFlags.DROP_ACTIVE state and any previously highlighted row will be unhighlighted.

The row will also be unhighlighted when the widget gets a drag leave event.

Parameters:

  • row — a GtkListBoxRow

drag_unhighlight_row

def drag_unhighlight_row(self) -> None

If a row has previously been highlighted via ListBox.drag_highlight_row, it will have the highlight removed.

get_activate_on_single_click

def get_activate_on_single_click(self) -> bool

Returns whether rows activate on single clicks.

get_adjustment

def get_adjustment(self) -> Adjustment | None

Gets the adjustment (if any) that the widget uses to for vertical scrolling.

get_row_at_index

def get_row_at_index(self, index_: int) -> ListBoxRow | None

Gets the n-th child in the list (not counting headers).

If index_ is negative or larger than the number of items in the list, None is returned.

Parameters:

  • index_ — the index of the row

get_row_at_y

def get_row_at_y(self, y: int) -> ListBoxRow | None

Gets the row at the y position.

Parameters:

  • y — position

get_selected_row

def get_selected_row(self) -> ListBoxRow | None

Gets the selected row, or None if no rows are selected.

Note that the box may allow multiple selection, in which case you should use ListBox.selected_foreach to find all selected rows.

get_selected_rows

def get_selected_rows(self) -> list[ListBoxRow]

Creates a list of all selected children.

get_selection_mode

def get_selection_mode(self) -> SelectionMode

Gets the selection mode of the listbox.

get_show_separators

def get_show_separators(self) -> bool

Returns whether the list box should show separators between rows.

get_tab_behavior

def get_tab_behavior(self) -> ListTabBehavior

Returns the behavior of the <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> keys.

insert

def insert(self, child: Widget, position: int) -> None

Insert the child into the box at position.

If a sort function is set, the widget will actually be inserted at the calculated position.

If position is -1, or larger than the total number of items in the box, then the child will be appended to the end.

Parameters:

  • child — the GtkWidget to add
  • position — the position to insert child in

invalidate_filter

def invalidate_filter(self) -> None

Update the filtering for all rows.

Call this when result of the filter function on the box is changed due to an external factor. For instance, this would be used if the filter function just looked for a specific search string and the entry with the search string has changed.

invalidate_headers

def invalidate_headers(self) -> None

Update the separators for all rows.

Call this when result of the header function on the box is changed due to an external factor.

invalidate_sort

def invalidate_sort(self) -> None

Update the sorting for all rows.

Call this when result of the sort function on the box is changed due to an external factor.

prepend

def prepend(self, child: Widget) -> None

Prepend a widget to the list.

If a sort function is set, the widget will actually be inserted at the calculated position.

Parameters:

  • child — the GtkWidget to add

remove

def remove(self, child: Widget) -> None

Removes a child from box.

Parameters:

  • child — the child to remove

remove_all

def remove_all(self) -> None

Removes all rows from box.

This function does nothing if box is backed by a model.

select_all

def select_all(self) -> None

Select all children of box, if the selection mode allows it.

select_row

def select_row(self, row: ListBoxRow | None = ...) -> None

Make row the currently selected row.

Parameters:

  • row — The row to select

selected_foreach

def selected_foreach(self, func: ListBoxForeachFunc) -> None

Calls a function for each selected child.

Note that the selection cannot be modified from within this function.

Parameters:

  • func — the function to call for each selected child

set_activate_on_single_click

def set_activate_on_single_click(self, single: bool) -> None

If single is True, rows will be activated when you click on them, otherwise you need to double-click.

Parameters:

  • single — a boolean

set_adjustment

def set_adjustment(self, adjustment: Adjustment | None = ...) -> None

Sets the adjustment (if any) that the widget uses to for vertical scrolling.

For instance, this is used to get the page size for PageUp/Down key handling.

In the normal case when the box is packed inside a GtkScrolledWindow the adjustment from that will be picked up automatically, so there is no need to manually do that.

Parameters:

  • adjustment — the adjustment

set_filter_func

def set_filter_func(self, filter_func: ListBoxFilterFunc | None = ...) -> None

By setting a filter function on the box one can decide dynamically which of the rows to show.

For instance, to implement a search function on a list that filters the original list to only show the matching rows.

The filter_func will be called for each row after the call, and it will continue to be called each time a row changes (via ListBoxRow.changed) or when ListBox.invalidate_filter is called.

Note that using a filter function is incompatible with using a model (see ListBox.bind_model).

Parameters:

  • filter_func — callback that lets you filter which rows to show

set_header_func

def set_header_func(self, update_header: ListBoxUpdateHeaderFunc | None = ...) -> None

Sets a header function.

By setting a header function on the box one can dynamically add headers in front of rows, depending on the contents of the row and its position in the list.

For instance, one could use it to add headers in front of the first item of a new kind, in a list sorted by the kind.

The update_header can look at the current header widget using ListBoxRow.get_header and either update the state of the widget as needed, or set a new one using ListBoxRow.set_header. If no header is needed, set the header to None.

Note that you may get many calls update_header to this for a particular row when e.g. changing things that don’t affect the header. In this case it is important for performance to not blindly replace an existing header with an identical one.

The update_header function will be called for each row after the call, and it will continue to be called each time a row changes (via ListBoxRow.changed) and when the row before changes (either by ListBoxRow.changed on the previous row, or when the previous row becomes a different row). It is also called for all rows when ListBox.invalidate_headers is called.

Parameters:

  • update_header — callback that lets you add row headers

set_placeholder

def set_placeholder(self, placeholder: Widget | None = ...) -> None

Sets the placeholder widget that is shown in the list when it doesn't display any visible children.

Parameters:

  • placeholder — a GtkWidget

set_selection_mode

def set_selection_mode(self, mode: SelectionMode | int) -> None

Sets how selection works in the listbox.

Parameters:

  • mode — The GtkSelectionMode

set_show_separators

def set_show_separators(self, show_separators: bool) -> None

Sets whether the list box should show separators between rows.

Parameters:

  • show_separatorsTrue to show separators

set_sort_func

def set_sort_func(self, sort_func: ListBoxSortFunc | None = ...) -> None

Sets a sort function.

By setting a sort function on the box one can dynamically reorder the rows of the list, based on the contents of the rows.

The sort_func will be called for each row after the call, and will continue to be called each time a row changes (via ListBoxRow.changed) and when ListBox.invalidate_sort is called.

Note that using a sort function is incompatible with using a model (see ListBox.bind_model).

Parameters:

  • sort_func — the sort function

set_tab_behavior

def set_tab_behavior(self, behavior: ListTabBehavior | int) -> None

Sets the behavior of the <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> keys.

Parameters:

  • behavior — the tab behavior

unselect_all

def unselect_all(self) -> None

Unselect all children of box, if the selection mode allows it.

unselect_row

def unselect_row(self, row: ListBoxRow) -> None

Unselects a single row of box, if the selection mode allows it.

Parameters:

  • row — the row to unselect

Properties

accept_unpaired_release

accept_unpaired_release: bool  # read/write

Whether to accept unpaired release events.

activate_on_single_click

activate_on_single_click: bool  # read/write

Determines whether children can be activated with a single click, or require a double-click.

selection_mode

selection_mode: SelectionMode | int  # read/write

The selection mode used by the list box.

show_separators

show_separators: bool  # read/write

Whether to show separators between rows.

tab_behavior

tab_behavior: ListTabBehavior | int  # read/write

Behavior of the <kbd>Tab</kbd> key

Signals

activate-cursor-row

def on_activate_cursor_row(self) -> None: ...

Emitted when the cursor row is activated.

move-cursor

def on_move_cursor(self, step: MovementStep, count: int, extend: bool, modify: bool) -> None: ...

Emitted when the user initiates a cursor movement.

The default bindings for this signal come in two variants, the variant with the Shift modifier extends the selection, the variant without the Shift modifier does not. There are too many key combinations to list them all here.

  • <kbd>←</kbd>, <kbd>→</kbd>, <kbd>↑</kbd>, <kbd>↓</kbd> move by individual children
  • <kbd>Home</kbd>, <kbd>End</kbd> move to the ends of the box
  • <kbd>PgUp</kbd>, <kbd>PgDn</kbd> move vertically by pages

row-activated

def on_row_activated(self, row: ListBoxRow) -> None: ...

Emitted when a row has been activated by the user.

row-selected

def on_row_selected(self, row: ListBoxRow | None) -> None: ...

Emitted when a new row is selected, or (with a None row) when the selection is cleared.

When the box is using SelectionMode.MULTIPLE, this signal will not give you the full picture of selection changes, and you should use the ListBox.selected-rows-changed signal instead.

select-all

def on_select_all(self) -> None: ...

Emitted to select all children of the box, if the selection mode permits it.

This is a keybinding signal.

The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>a</kbd>.

selected-rows-changed

def on_selected_rows_changed(self) -> None: ...

Emitted when the set of selected rows changes.

toggle-cursor-row

def on_toggle_cursor_row(self) -> None: ...

Emitted when the cursor row is toggled.

The default bindings for this signal is <kbd>Ctrl</kbd>+<kbd>␣</kbd>.

unselect-all

def on_unselect_all(self) -> None: ...

Emitted to unselect all children of the box, if the selection mode permits it.

This is a keybinding signal.

The default binding for this signal is <kbd>Ctrl</kbd>-<kbd>Shift</kbd>-<kbd>a</kbd>.