ListStore
| Anke (encarsia) | Also available in: Deutsch
Store data sets in ListStores and use ComboBox and TreeView to display the data
There are a bunch of elements required to store and display tables of data in GTK+ applications:
- The model to administrate data. There are two types:
ListStore: flat table, besides string and numerical values the rows also can be of GTK+ element type (like buttons or checkboxes), input of data sets in Glade possible
TreeStore: just like ListStore but rows can possess child rows, input of data sets in Glade is not possible (see also TreeStore article)
- Widgets:
TreeView: show, sort and edit data; used by both store model types; a data store can be used my multiple TreeView widgets
ComboBox: comboboxes are used to limit input to given list items, this list can be stored in a List/TreeStore (see also spinbutton and combobox article)
CellRenderers: Subwidgets to specify source, layout and other properties (like being editable) of displayed data rows
Glade
ListStore
In the example there is one ListStore created via "Miscellaneous > List Store" which will be later used by three Widgets.
First there are some rows created. ListStore data sets can be inserted in Glade but this in practise is only convenient for typing in few data sets.
Content changes in the ListStore are simultaneously updated in the Widgets using the ListStore. For individual sorting of the same List/TreeStore it is needed to create Gtk.TreeModelSort elements (this element is used in the example of the TreeStore article).
Widgets
- ComboBox
-
Creating the widget you are prompted to choose as "TreeView Model". In the edit mode accessible via "Edit > Hierarchy" there is created a CellRendererText. In the first field ("Text") the column to load the items of the dropdown menu from is set. To process the selection you will need the changed signal.
- TreeView #1
-
The first TreeView widget is placed within a Gtk.ScrolledWindow container. Like in a ComboBox there are created CellRenderers representing a column to show in the TreeView table. If the sort indicator is activated columns can be sorted on a column table click. Columns do not have to be sorted according to the columns they show.
- TreeView #2
-
The second TreeView widget is created within a Gtk.ViewPort. This container widget does not provide scroll bars but the automatically adapts the necessary size to display the whole content. So for larger tables you will need the Gtk.ScrolledWindow. The sort indicator is deactivated and the middle column ("Description") is made editible with the signal "edited" allocated.
- Button
-
The button's function is appending a row to the ListStore, so the clicked signal is required.
Python
TreeStore
The ListStore's row can be iterated over via for row in store
. New rows are added by append
, other options are insert
or remove
to add or delete rows at specific positions.
ComboBox
For accessing a data row you need a Gtk.TreeIter object which points to the position in the model (this can also be achieved by a Gtk.TreePath object).
iter,model = widget.get_active_iter(),widget.get_model() row = model[iter] print("Selection:",row[0])
Edit cells
The edited signal passes the position and content of the edited cell. The new content of the CellRendererText has to explicitly be committed to the data store otherwise the content will return to the pre edit state. This can be accomplished by using the passed TreePath position.
def on_cellrenderer_descr_edited(self,widget,pos,edit): x.store[int(pos)][1] = edit
Listings
Glade
<?xml version="1.0" encoding="UTF-8"?> <!-- Generated with glade 3.20.0 --> <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkListStore" id="liststore"> <columns> <!-- column-name name --> <column type="gchararray"/> <!-- column-name descr --> <column type="gchararray"/> <!-- column-name num --> <column type="gint"/> </columns> <data> <row> <col id="0" translatable="yes">one</col> <col id="1" translatable="yes">textextext</col> <col id="2">12345</col> </row> <row> <col id="0" translatable="yes">two</col> <col id="1" translatable="yes">bla blubb</col> <col id="2">479</col> </row> <row> <col id="0" translatable="yes">three</col> <col id="1" translatable="yes">nö</col> <col id="2">0</col> </row> </data> </object> <object class="GtkWindow" id="window"> <property name="width_request">300</property> <property name="can_focus">False</property> <signal name="destroy" handler="on_window_destroy" swapped="no"/> <child> <object class="GtkBox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkComboBox" id="cbox"> <property name="visible">True</property> <property name="can_focus">False</property> <property name="model">liststore</property> <property name="entry_text_column">0</property> <signal name="changed" handler="on_cbox_changed" swapped="no"/> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">0</attribute> </attributes> </child> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkBox"> <property name="width_request">150</property> <property name="height_request">250</property> <property name="visible">True</property> <property name="can_focus">False</property> <property name="orientation">vertical</property> <child> <object class="GtkScrolledWindow"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="shadow_type">in</property> <child> <object class="GtkTreeView"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="model">liststore</property> <property name="headers_clickable">False</property> <child internal-child="selection"> <object class="GtkTreeSelection"/> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Name</property> <property name="sort_indicator">True</property> <property name="sort_column_id">0</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">0</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Description</property> <property name="sort_indicator">True</property> <property name="sort_column_id">2</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">1</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Number</property> <property name="sort_indicator">True</property> <property name="sort_column_id">2</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">2</attribute> </attributes> </child> </object> </child> </object> </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> <object class="GtkViewport"> <property name="visible">True</property> <property name="can_focus">False</property> <child> <object class="GtkTreeView"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="model">liststore</property> <child internal-child="selection"> <object class="GtkTreeSelection"/> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Name</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">0</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Description</property> <child> <object class="GtkCellRendererText" id="cellrenderer_descr"> <property name="editable">True</property> <signal name="edited" handler="on_cellrenderer_descr_edited" swapped="no"/> </object> <attributes> <attribute name="text">1</attribute> </attributes> </child> </object> </child> <child> <object class="GtkTreeViewColumn"> <property name="title" translatable="yes">Number</property> <child> <object class="GtkCellRendererText"/> <attributes> <attribute name="text">2</attribute> </attributes> </child> </object> </child> </object> </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> </object> <packing> <property name="expand">True</property> <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <object class="GtkButton" id="add_row_button"> <property name="label">gtk-add</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> <property name="use_stock">True</property> <property name="always_show_image">True</property> <signal name="clicked" handler="on_add_row_button_clicked" swapped="no"/> </object> <packing> <property name="expand">False</property> <property name="fill">True</property> <property name="position">2</property> </packing> </child> </object> </child> <child type="titlebar"> <placeholder/> </child> </object> </interface>
Python
#!/usr/bin/python # -*- coding: utf-8 -*- import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk class Handler: def on_window_destroy(self, *args): Gtk.main_quit() def on_cbox_changed(self, widget): iter, model = widget.get_active_iter(), widget.get_model() row = model[iter] print("Selection:", row[0]) def on_cellrenderer_descr_edited(self, widget, pos, edit): x.store[int(pos)][1] = edit def on_add_row_button_clicked(self,widget): x.store.append(list(x.more_rows[len(x.store) - 3])) #set button inactive when all rows are appended if len(x.store) == 7: x.button.set_sensitive(False) class Example: def __init__(self): self.builder = Gtk.Builder() self.builder.add_from_file("09_liststore.glade") self.builder.connect_signals(Handler()) window = self.builder.get_object("window") window.show_all() self.button = self.builder.get_object("add_row_button") self.store = self.builder.get_object("liststore") #print all values [print(row[:]) for row in self.store] self.more_rows = [("four", "", 5739), ("five", "", 120), ("six", "", 4), ("seven", "lucky number", 7), ] def main(self): Gtk.main() x = Example() x.main()
Comments
Comments powered by Disqus