Part 1 of this pygtk tutorial stopped with a working toolbar and two place holders. But this is obviously not enough to create complicated UIs.
Tables allow packing multiple widgets together. The principle is quite simple. Think of a chess-board with coordinate system, and you can place different text areas, buttons and other widgets inside the place holders. Here is how a table with multiple labels, text widgets and a check button looks like this in asunder:
This table has 8 elements, in it, however its size is 3 by 3. Here is how this table is created:
album_table = gtk.Table(3, 3, False)
The 3 arguments (
False) determines whether this table is homogeneous or
not. If set to True, all elements in the table will be the same size.
Then the table is added to the main window with packing:
The table is populated using the method:
table.attach(widget, left, right, top, bottom, xoptions, yoptions, xpadding, ypadding)
And the coordinate system start from the top left corner. Translated to
this coordinate system, the album info in
asunder looks like that:
0 1 2 3 0 +---------------+----------+--------------+ | Artist label | Text | Check Button | 1 +---------------+----------+--------------+ | Title label | Text | Empty | 2 +---------------+----------+--------------+ | Genere/Year | Text | Number | 3 +---------------+----------+--------------+
The table would then be populated with the first Widget like this:
artist_label = gtk.Label('Album Artist:') album_table.attach(artist_label, 0, 1, 0, 1)
The text widget is also inserted:
artist_name = gtk.Entry(128) artist_name.set_text("Unknown Artist")
Note that the
gtk.Entry init method takes an integer as an argument.
This number specifies the letters allowed text in this box. 128 Letter
should be decent length to an album name.
gtk.Entry widget is created, the method
the default text to displayed in the text area.
CheckButton widget is added in the top right corner:
single_artist = gtk.CheckButton("Single Artist") album_table.attach(single_artist, 2, 3, 0, 1)
gtk.CheckButton init method takes a String as an argument. This
string will be shown next to the check button. By now, the UI created
with table populated with 3 widgets looks like this:
Packing the rest of the widget into the table is not so hard now. You can find the code that shows that in the table_complete tag, which will produce the following UI:
Now that the table containing the album information, it is time to look
on populating the list of tracks using two of the more complicated GTK
Asunder populated the list of album tracks inside a
TreeView expects a
gtk.ListStore widget to be handed over when creating
it. Hence, before a TreeView can be created, a ListStore has to be created with
some thought on what has to be stored in it:
# We begin with creating a ListStore liststore = gtk.ListStore(bool,int,str,str,str)
This list store has 5 items (which will be than translated to 5 columns in the
TreeView). The first item is of type
bool, to indicate
second is of type
int to indicate track number; the third and fourth are both
strings to indicate the track artist and title respectively. The last item is
also a string, although a tracks length is actually a number.
gtk.ListStore is properly created with the correct fields to hold,
gtk.TreeView widget can be created:
treeview = gtk.TreeView(liststore)
The created widget is empty and has no columns; a column is add with
gtk.TreeViewColumn and attaching
gtk.CellRendererText widget to it:
rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Rip", rendererText, text=0) column.set_sort_column_id(0) treeView.append_column(column)
The above code snipped has to be repeated for every column, hence it will not
be displayed here. Another thing to be noticed here, which is not inside the
scope of GTK programming, but rather in the scope of good coding, is the length
of the current
__init__ function. If all the columns that need to be created,
are directly created inside the
__init__ method, it will be a very long and
complicated to understand. This will make it hard to maintain and change later.
Hence, it is better to have a small method that wrapped all the code related to
making the columns inside a class method
def create_columns(self, treeView).
Hence, the UI class will now look like:
class PunderUI(): """ Initial class to draw the first toolbar. """ def help_dialog(self, widget): ... def create_columns(self, treeView): """ create columns for treeview of track list """ rendererText = gtk.CellRendererText() column = gtk.TreeViewColumn("Rip", rendererText, text=0) column.set_sort_column_id(0) treeView.append_column(column) ... def __init__(self): """ create the gui using GTK Window, and Toolbar. """ window = gtk.Window() window.set_default_size(500, -1) vbox = gtk.VBox() window.add(vbox) ... liststore = gtk.ListStore(bool,int,str,str,str) treeview = gtk.TreeView(liststore) ... # populate the treeview widget with columns self.create_columns(treeview)
The result of populating
treeview with columns is:
ListStore object created earlier is empty, so is the
Hence, it makes sense to populate
liststore with some dummy data, just so
it will be visible.
ListStore is populated with the method
takes an iterable as an argument. This iterable has to match in size the size
declared when creating the
ListStore object. The items inside this iterable
should also match the types declared earlier:
# dummy function for i in range(1,6): liststore.append([True,i,"bar","baz","zap"])
Put together, the above snippets create a poplluated
ListStore inside a
The code to produce this UI can be found in the github brach simplified tree view. The UI is almost complete. However, there is more work to do. So, stay tuned for part tree.