16.2. ComboBox and ComboBoxEntry Widgets
Prev | Chapter 16. New Widgets in PyGTK 2.4 | Next

## 16.2. ComboBox and ComboBoxEntry Widgets

### 16.2.1. ComboBox Widgets

The `ComboBox` replaces the `OptionMenu` with a powerful widget that uses a `TreeModel` (usually a `ListStore`) to provide the list items to display. The `ComboBox` implements the `CellLayout` interface that provides a number of methods for managing the display of the list items. One or more `CellRenderers` can be packed into a `ComboBox` to customize the list item display.

#### 16.2.1.1. Basic ComboBox Use

The easy way to create and populate a `ComboBox` is to use the convenience function:

      combobox = gtk.combo_box_new_text()

This function creates a `ComboBox` and its associated `ListStore` and packs it with a `CellRendererText`. The following convenience methods are used to populate or remove the contents of the `ComboBox` and its `ListStore`:

      combobox.append_text(text)
      combobox.prepend_text(text)
      combobox.insert_text(position, text)
      combobox.remove_text(position)

where `text` is the string to be added to the `ComboBox` and `position` is the index where `text` is to be inserted or removed. In most cases the convenience function and methods are all you need.

The example program comboboxbasic.py demonstrates the use of the above function and methods. Figure 16.5, “Basic ComboBox” illustrates the program in operation:

Figure 16.5. Basic ComboBox

Unfortunately, the `GTK`+ developers did not provide a convenience method to retrieve the active text. That would seem to be a useful method. You'll have to create your own similar to:

      def get_active_text(combobox):
          model = combobox.get_model()
          active = combobox.get_active()
          if active < 0:
              return None
          return model[active][0]

The index of the active item is retrieved using the method:

      active = combobox.get_active()

The active item can be set using the method:

      combobox.set_active(index)

where `index` is an integer larger than -2. If `index` is -1 there is no active item and the ComboBox display will be blank. If `index` is less than -1, the call will be ignored. If `index` is greater than -1 the list item with that index value will be displayed.

You can connect to the "changed" signal of a `ComboBox` to be notified when the active item has been changed. The signature of the "changed" handler is:

      def changed_cb(combobox, ...):

where `...` represents the zero or more arguments passed to the `GObject.connect`() method.

#### 16.2.1.2. Advanced ComboBox Use

Creating a `ComboBox` using the `gtk.combo_box_new_text`() function is roughly equivalent to the following code:

      liststore = gtk.ListStore(str)
      combobox = gtk.ComboBox(liststore)
      cell = gtk.CellRendererText()
      combobox.pack_start(cell, True)
      combobox.add_attribute(cell, 'text', 0)

To make use of the power of the various `TreeModel` and `CellRenderer` objects you need to construct a `ComboBox` using the constructor:

      combobox = gtk.ComboBox(model=None)

where `model` is a `TreeModel`. If you create a `ComboBox` without associating a `TreeModel`, you can add one later using the method:

      combobox.set_model(model)

The associated `TreeModel` can be retrieved using the method:

      model = combobox.get_model()

Some of the things you can do with a `ComboBox` are:

- Share the same `TreeModel` with other `ComboBox`es and `TreeView`s.
- Display images and text in the `ComboBox` list items.
- Use an existing `TreeStore` or `ListStore` as the model for the `ComboBox` list items.
- Use a `TreeModelSort` to provide a sorted `ComboBox` list.
- Use a `TreeModelFilter` to use a subtree of a `TreeStore` as the source for a `ComboBox` list items.
- Use a `TreeModelFilter` to use a subset of the rows in a `TreeStore` or `ListStore` as the `ComboBox` list items.
- Use a cell data function to modify or synthesize the display for list items.

The use of the `TreeModel` and `CellRenderer` objects is detailed in Chapter 14, Tree View Widget.

The `ComboBox` list items can be displayed in a grid if you have a large number of items to display. Otherwise the list will have scroll arrows if the entire list cannot be displayed. The following method is used to set the number of columns to display:

      combobox.set_wrap_width(width)

where `width` is the number of columns of the grid displaying the list items. For example, the comboboxwrap.py program displays a list of 50 items in 5 columns. Figure 16.6, “ComboBox with Wrapped Layout” illustrates the program in operation:

Figure 16.6. ComboBox with Wrapped Layout

With a large number of items, say more than 50, the use of the `set_wrap_width`() method will have poor performance because of the computation for the grid layout. To get a feel for the affect modify the comboboxwrap.py program line 18 to display 150 items.

            for n in range(150):

Run the program and get a time estimate for startup. Then modify it by commenting out line 17:

            #combobox.set_wrap_width(5)

Run and time it again. It should start up significantly faster. My experience is about 20 times faster.

In addition to the `get_active`() method described above, you can retrieve a `TreeIter` pointing at the active row by using the method:

      iter = combobox.get_active_iter()

You can also set the active list item using a `TreeIter` with the method:

      combobox.set_active_iter(iter)

The `set_row_span_column`() and `set_column_span_column`() methods are supposed to allow the specification of a `TreeModel` column number that contains the number of rows or columns that the list item is supposed to span in a grid layout. Unfortunately, in GTK+ 2.4 these methods are broken.

Since the `ComboBox` implements the `CellLayout` interface which has similar capabilities as the `TreeViewColumn` (see Section 14.5, “TreeViewColumns” for more information). Briefly, the interface provides:

      combobox.pack_start(cell, expand=True)
      combobox.pack_end(cell, expand=True)
      combobox.clear()

The first two methods pack a `CellRenderer` into the `ComboBox` and the `clear`() method clears all attributes from all `CellRenderer`s.

The following methods:

      comboboxentry.add_attribute(cell, attribute, column)

      comboboxentry.set_attributes(cell, ...)

set attributes for the `CellRenderer` specified by `cell`. The `add_attribute`() method takes a string `attribute` name (e.g. 'text') and an integer `column` number of the column in the `TreeModel` to use to set `attribute`. The additional arguments to the `set_attributes`() method are `attribute=column` pairs (e.g text=1).

### 16.2.2. ComboBoxEntry Widgets

The `ComboBoxEntry` widget replaces the `Combo` widget. It is subclassed from the `ComboBox` widget and contains a child `Entry` widget that has its contents set by selecting an item in the dropdown list or by direct text entry either from the keyboard or by pasting from a `Clipboard` or a selection.

#### 16.2.2.1. Basic ComboBoxEntry Use

Like the `ComboBox`, the `ComboBoxEntry` can be created using the convenience function:

      comboboxentry = gtk.combo_box_entry_new_text()

The `ComboBoxEntry` should be populated using the `ComboBox` convenience methods described in Section 16.2.1.1, “Basic ComboBox Use”.

Since a `ComboBoxEntry` widget is a `Bin` widget its child `Entry` widget is available using the "child" attribute or the `get_child`() method:

      entry = comboboxentry.child
      entry = comboboxentry.get_child()

You can retrieve the `Entry` text using its `get_text`() method.

Like the `ComboBox`, you can track changes in the active list item by connecting to the "changed" signal. Unfortunately, this doesn't help track changes to the text in the `Entry` child that are direct entry. When a direct entry is made to the child `Entry` widget the "changed" signal will be emitted but the index returned by the `get_active`() method will be -1. To track all changes to the `Entry` text, you'll have to use the `Entry` "changed" signal. For example:

      def changed_cb(entry):
          print entry.get_text()

      comboboxentry.child.connect('changed', changed_cb)

will print out the text after every change in the child `Entry` widget. For example, the comboboxentrybasic.py program demonstrates the use of the convenience API. Figure 16.7, “Basic ComboBoxEntry” illustrates the program in operation:

Figure 16.7. Basic ComboBoxEntry

Note that when the `Entry` text is changed due to the selection of a dropdown list item the "changed" handler is called twice: once when the text is cleared; and, once when the text is set with the selected list item text.

#### 16.2.2.2. Advanced ComboBoxEntry Use

The constructor for a ComboBoxEntry is:

      comboboxentry = gtk.ComboBoxEntry(model=None, column=-1)

where `model` is a `TreeModel` and `column` is the number of the column in `model` to use for setting the list items. If column is not specified the default value is -1 which means the text column is unset.

Creating a `ComboBoxEntry` using the convenience function `gtk.combo_box_entry_new_text`() is equivalent to the following:

      liststore = gtk.ListStore(str)
      comboboxentry = gtk.ComboBoxEntry(liststore, 0)

The `ComboBoxEntry` adds a couple of methods that are used to set and retrieve the `TreeModel` column number to use for setting the list item strings:

      comboboxentry.set_text_column(text_column)
      text_column = comboboxentry.get_text_column()

The text column can also be retrieved and set using the "text-column" property. See Section 16.2.1.2, “Advanced ComboBox Use” for more information on the advanced use of the `ComboBoxEntry`.

### Note

Your application must set the text column for the `ComboBoxEntry` to set the `Entry` contents from the dropdown list. The text column can only be set once, either by using the constructor or by using the `set_text_column`() method.

When a `ComboBoxEntry` is created it is packed with a new `CellRendererText` which is not accessible. The 'text' attribute for the `CellRendererText` has to be set as a side effect of setting the text column using the `set_text_column`() method. You can pack additional `CellRenderer`s into a `ComboBoxEntry` for display in the dropdown list. See Section 16.2.1.2, “Advanced ComboBox Use” for more information.

Prev | Up | Next
Chapter 16. New Widgets in PyGTK 2.4 | Home | 16.3. ColorButton and FontButton Widgets