Scrolling List Boxes

Applications such as the iTunes¨ browser present lists of items in (multiple) scrolling boxes.  When the user selects an item in a scrolling list box, information might then be updated in other areas of the window, and the user can select a command to remove or rename the selected item, among other things.

The window of a demo program that displays a list of fruits in a scrolling list box is shown below. 

 

 

The selected fruit is also displayed in a text field, as is its index position (counting from 0) in the list.  The user can enter a new fruit name in the input field and add it to the list by pressing the Add button.  Pressing Remove deletes the selected fruit from the list and updates the display fields.  When the last remaining fruit is deleted, the Remove button is disabled to prevent further deletions.

Although the userÕs interactions with this application in this are fairly simple, the code that supports it is rather complicated.  Therefore, the programÕs functions are best discussed in small pieces.  The complete program is in listboxdemo.py.

The the __init__ method sets up the widgets for the programÕs window, as usual.

   

 

# Set up the list box

# Note the event handler parameter for selecting a list item

self.listBox = self.addListbox(row = 0, column = 0, rowspan = 4,

                              listItemSelected = self.listItemSelected)

 

# Add some items to the list box and select the first one

self.listBox.insert(END, "Apple")

self.listBox.insert(END, "Banana")

self.listBox.insert(END, "Cherry")

self.listBox.insert(END, "Orange")

self.listBox.setSelectedIndex(0)

 

# Set up the labels, fields, and buttons

self.addLabel(text = "Input", row = 0, column = 1)

self.addLabel(text = "Index", row = 1, column = 1)

self.addLabel(text = "Current item", row = 2, column = 1)

self.inputField = self.addTextField(text = "", row = 0,

                                    column = 2, width = 10)

self.indexField = self.addIntegerField(value = "", row = 1,

                                       column = 2, width = 10)

self.itemField = self.addTextField(text = "", row = 2,

                                   column = 2, width = 10)

self.addButton(text = "Add", row = 3,

               column = 1, command = self.add)

self.removeButton = self.addButton(text = "Remove", row = 3,

                                   column = 2, command = self.remove)

 

# Display current index and currently selected item

self.listItemSelected(0)

 

 

The method addListbox creates a list box and adds it to the window.  This method also returns the new list box as an object of the class EasyListbox, an extension of the class tkinter.Listbox. 

When a list box is added to the window with breezypythongui, the programmer can supply an event handler method, in this case, the method listItemSelected.  This method will be triggered when the user selects an item in the list box.  The application should define this method to expect one argument.  When the method is triggered, it will receive the index of the selected item as this argument.  Note that application also calls this method as the final step in the setup code.

A list box may be initially empty, but this application adds four strings to it.  The Listbox method insert expects and integer position and a string as arguments.  The string is inserted before an item at that position in the list box, if that item exists.  The use of the tkinter constant END for this position places the string at the end of the current list.  The setup code also selects an item in the list box, using the method setSelectedIndex.

The rest of the setup code adds labels, text fields, and command buttons to the window in the usual manner.

When the user selects an item in the list box, the itemÕs index is passed to listItemSelected method.  This method responds to a button click in the list box by updating the index and item fields with the itemÕs index and name.  The EasyListbox method getSelectedItem returns the currently selected item.

 

def listItemSelected(self, index):

    """Responds to the selection of an item in the list box.

    Updates the fields with the current item and its index."""

    self.indexField.setNumber(index)

    self.itemField.setText(self.listBox.getSelectedItem())

 

 

When the user presses the Add button, the add method is triggered.  If the input field is empty, this method does nothing.  Otherwise, there are two cases.  If the list box is empty (no item is selected), then the input fieldÕs text is inserted at position 0 in the list, this position is selected, the fields are updated, and the Remove button is enabled.  Otherwise, the input fieldÕs text is inserted before the currently selected item and the index field is updated (the selected itemÕs position has been incremented by 1).  Finally, if an item has been added to the list, the input field is cleared.

 

def add(self):

        """If an input is present, insert it before the selected

        item in the list box.  The selected item remains current.

        If the first item is added, select it and enable the

        remove button."""

        item = self.inputField.getText()

        if item != "":

            index = self.listBox.getSelectedIndex()

            if index == -1:

                self.listBox.insert(0, item)

                self.listBox.setSelectedIndex(0)

                self.listItemSelected(0)

                self.removeButton["state"] = NORMAL

            else:

                self.listBox.insert(index, item)

                self.listItemSelected(index + 1)

            self.inputField.setText("")

 

 

When the user presses the Remove button, the remove method is triggered.   Because the button is enabled only when the list box is not empty, the remove method does not have to consider the case of an empty list.  The method begins by getting the index of the selected item and passing the index to the Listbox method delete.  Then there are three cases to consider when updating the contents of the window.  If the list box is now empty, the item field is cleared, the index field is set to -1, and the Remove button is disabled.  Otherwise, if the deleted item was the first one in the list, the item following it is selected.  Otherwise, the item before it is selected.  In the latter two cases, the contents of the index field do not change, but the item field is updated.

 

def remove(self):

    """If there are items in the list, remove

    the selected item, select previous one,

    and update the fields.  If there was no previous

    item, select the next one.  If the last item is

    removed, disable the remove button."""

    index = self.listBox.getSelectedIndex()

    self.listBox.delete(index)

    if self.listBox.size() > 0:

        if index > 0:

            index -= 1

        self.listBox.setSelectedIndex(index)

        self.listItemSelected(index)

    else:

        self.listItemSelected(-1)

        self.removeButton["state"] = DISABLED

 

 

The next table summarizes the methods used to manipulate a list box in breezypythongui.

 

EasyListbox Method

What it does

insert(index, item)

Inserts the item before the given position in the list box.  When index is tkinter.END, the item goes at the end of the list box.

delete(index)

Removes the item at index from the list box.

size()

Returns the number of items in the list box.

getSelectedIndex()

Returns the index of the selected item, or   -1 if no item is selected or the list box is empty.

setSelectedIndex(index)

Selects the item at index in the list box.

getSelectedItem()

Returns the selected item in the list box.