WxPython - ListBox - Fill From List, Handle SelectionEvents

May 20, 2018 Oclemy Python GUI 8 minutes, 0 seconds

This is a wxPython ListBox example and tutorial. In this tutorial, we want to see how to populate wxPython ListBox from a list of data and handle itemClick events. We will lean about listbox data population and selection.

In this wxPython example, we will see how to get the selected item and show in a message box. We

Common Questions this Tutorial Answers

  1. How do I populate a ListBox control with python list in wxPython.
  2. How do I handle selection of wxPython ListBox control.

We are Building a Vibrant YouTube Community

We have a fast rising YouTube Channel of friends. So far we've accumulated more than 2.6 million agreggate views and more than 10,000 subscribers. Here's the Channel: ProgrammingWizards TV.

Please go ahead subscribe(free obviously) as well. If you have a question or a comment you can post there instead of in this site.People are suggesting us tutorials to do there so you can too.

Here's this tutorial in Video Format.

Intoduction to Python Object Oriented Programming

First given that we always write Object oriented code, we need to get some things write and be familiar with the syntax.

1. Defining a Class in Python

Classes, in Object Oriented Programming, define the blueprint for creation of Objects.

Here's how a class is defined in Python:

class MyClass(MyParentClass):
    statement1
    statement2
    statement3

in which case the class name is the MyClass and it derives from MyParentClass. Then we have three statements as the body of the class.

2. What is the __init__ method in Python?

__init__ is a special method in Python that acts as the constructor for the class in which it is defined in.

A constructor is usually a special method that gets called every time an instance of a class is created.

3. What is self in Python?

self is a special variable which points to the current object. It is normally called this in languages like Java, C#, C++,PHP and Javascript. The object is passed implicitly to every method available in it, however we have to get it explicitly in every method while writing the methods.

4. What is __name__ in Python?

__name__ is a global variable that points to the namespace where the Python interpreter happens to be at the moment.

If you use it inside an imported module, then it will be the name of that module.

5. What is __main__ in Python?

__main__ is the name of the scope in which top-level code executes.

It is the entry point to your program.

Normally we use __name__ in modules, comparing it with __main__ to discover whether or not we are running in the main scope.

if __name__ == "__main__":
    # execute only if run as a script
    # maybe instantiate the app and run it.

Let's start.

index.py

We have a single python file called index.py.

Explanations

1. Import Required Packages

In this case we only one package: `wx:

import wx

Internally, wx package imports all items from the core wxPython module into itself, thus preventing us from having to import them one by one.

2. Create Wx.App class

Basically a class that derives from wx.App.

Usually all wxPython applications must create a wxPython application object. They create it from the App class defined in the wx package.It is this class that initializes and starts the underlying wxPyhon framework.

class MyApp(wx.App):

Then we implement the OnInit method from wx.App to create a frame and then call self.SetTopWindow(frame).

    def OnInit(self):
        self.frame = MrFrame(None)
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

As you can see we instantiate a class called MrFrame, and assign it to the frame property of our MyApp instance. The set the frame as our top window.

Then show the Frame via the Show() method.

3. Define Frame

First we create a class called MrFrame in my case, that derives from wx.Frame. A wx.Frame is a class that has a resizeable window.

class MrFrame(wx.Frame):

We will create our wxControls inside the __init__ method of our MrFrame class. Remember the __init__ is the constructor of a class.

In this case we pass the self which is the current object and the parent which is wx.Frame:

    def __init__(self, parent):

Then invoke the __init__ method of the wx.Frame class:

        wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=u"wxPython ListBox", pos=wx.DefaultPosition,
                          size=wx.Size(500, 400), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)

passing in the id, title, position, size and style.

Setting Background Color of the wxPython Frame

To set the background color of a wx.Frame instance, we use the SetBackgroundColour() method. self in this case refers to the current object of the MrFrame that actually inherits from wx.Frame class.

        self.SetBackgroundColour(wx.Colour(0, 128, 128))

Using a wxPython FlexGridSizer

A FlexGridSizer is a sizer which lays out its children in a two- dimensional table with all table fields in one row having the same height and all fields in one column having the same width, but all rows or all columns are not necessarily the same height or width as in the wxGridSizer.

We'll use it as our root layout.

        myFlexGridSizer = wx.FlexGridSizer(1, 1, 0, 0)
        myFlexGridSizer.SetFlexibleDirection(wx.BOTH)
        myFlexGridSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

Using a wxPython BoxGridSizer

A BoxGridSizer allows us arrange controls in a row or column.

In this case we arrange them in a column:

        myBoxGridSizer = wx.BoxSizer(wx.VERTICAL)

Creating a wxPython StaticText

A StaticText is a wxPython control that displays one or more lines of read-only text.

It is what is commonly referred to as the Label in GUI toolkits like Windows Forms, Swing and JavaFX.

        self.headerLabel = wx.StaticText(self, wx.ID_ANY, u"Nebulas in The Universe", wx.Point(-1, -1), wx.DefaultSize,
                                         0)
        self.headerLabel.Wrap(-1)
        self.headerLabel.SetFont(wx.Font(wx.NORMAL_FONT.GetPointSize(), 75, 90, 92, True, wx.EmptyString))

We'll add ours in a BoxGridSizer and align it horizontally, to allow us display it next to a TextCtrl.

        myBoxGridSizer.Add(self.headerLabel, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)

Create a Python List

We will create a Python List data structure and fill it with data. This will be our data source:

        mListBoxChoices = [u"Orion", u"Horse Head", u"Bernard 68", u"Ghost Head", u"Crab", u"Ant", u"Elephant's Trunk",
                           u"Wicth Head", u"Pelican", u"Helix", u"Own", u"Ring Nebular", u"Boomerang", u"Snake"]

Instantiate a wxPython ListBox and Fill With List

This is a wxPython ListBox tutorial. So we need instantiate a ListBox, setting it some properties:

        self.mListBox = wx.ListBox(self, wx.ID_ANY, wx.Point(-1, -1), wx.Size(300, 300), mListBoxChoices, wx.LB_SINGLE)

As you can see we've filled it with List by just passing in the python list as a parameter. This will populate our ListBox with data from the List.

Setting wxPython ListBox Font

We can do that via the SetFont() method:

        self.mListBox.SetFont(wx.Font(12, 75, 90, 90, False, wx.EmptyString))

Setup Layouts

Then we add our ListBox First to BoxGridSizer:

        myBoxGridSizer.Add(self.mListBox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)

        myFlexGridSizer.Add(myBoxGridSizer, 1, wx.EXPAND, 5)

        self.SetSizer(myFlexGridSizer)
        self.Layout()

        self.Centre(wx.BOTH)

then as you can see we've added the BoxGridSizer to our FlexGridSizer.

Bind ListBox Event to Event Handler

We want to listen to selectedItem events for our listbox and display the selected item in a messagebox.

We'll use the Bind() method defined in the ListBox class, passing in wx.EVT_LISTBOX event and our event handler.

        self.mListBox.Bind(wx.EVT_LISTBOX, self.showSelectedItem)

Create ListBox Selected Item Event Handler

This is the event handler that will be bound to the ListBox:

    def showSelectedItem(self, event):
        wx.MessageBox(event.GetEventObject().GetStringSelection(), "Cosmic News")

As you can see show a messagebox with the selected item.

The selected ListBox item can be found via event.GetEventObject().GetStringSelection() invokation.

Run app

We'll check if the scope is __main__, the top level scope, then instantiate the MyApp and invoke the MainLoop(). MainLoop() is the main GUI event loop.

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

Here's the full source code:

Full Code

import wx

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MrFrame(None)
        self.SetTopWindow(self.frame)
        self.frame.Show()
        return True

class MrFrame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, id=wx.ID_ANY, title=u"wxPython ListBox", pos=wx.DefaultPosition,
                          size=wx.Size(500, 400), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)

        self.SetSizeHintsSz(wx.DefaultSize, wx.DefaultSize)
        self.SetBackgroundColour(wx.Colour(0, 128, 128))

        myFlexGridSizer = wx.FlexGridSizer(1, 1, 0, 0)
        myFlexGridSizer.SetFlexibleDirection(wx.BOTH)
        myFlexGridSizer.SetNonFlexibleGrowMode(wx.FLEX_GROWMODE_SPECIFIED)

        myBoxGridSizer = wx.BoxSizer(wx.VERTICAL)

        self.headerLabel = wx.StaticText(self, wx.ID_ANY, u"Nebulas in The Universe", wx.Point(-1, -1), wx.DefaultSize,
                                         0)
        self.headerLabel.Wrap(-1)
        self.headerLabel.SetFont(wx.Font(wx.NORMAL_FONT.GetPointSize(), 75, 90, 92, True, wx.EmptyString))

        myBoxGridSizer.Add(self.headerLabel, 0, wx.ALL | wx.ALIGN_CENTER_HORIZONTAL, 5)

        mListBoxChoices = [u"Orion", u"Horse Head", u"Bernard 68", u"Ghost Head", u"Crab", u"Ant", u"Elephant's Trunk",
                           u"Wicth Head", u"Pelican", u"Helix", u"Own", u"Ring Nebular", u"Boomerang", u"Snake"]
        self.mListBox = wx.ListBox(self, wx.ID_ANY, wx.Point(-1, -1), wx.Size(300, 300), mListBoxChoices, wx.LB_SINGLE)
        self.mListBox.SetFont(wx.Font(12, 75, 90, 90, False, wx.EmptyString))

        myBoxGridSizer.Add(self.mListBox, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)

        myFlexGridSizer.Add(myBoxGridSizer, 1, wx.EXPAND, 5)

        self.SetSizer(myFlexGridSizer)
        self.Layout()

        self.Centre(wx.BOTH)

        # Connect Events
        self.mListBox.Bind(wx.EVT_LISTBOX, self.showSelectedItem)

    def __del__(self):
        pass

    # Virtual event handlers, overide them in your derived class
    def showSelectedItem(self, event):
        wx.MessageBox(event.GetEventObject().GetStringSelection(), "Cosmic News")

if __name__ == "__main__":
    app = MyApp(False)
    app.MainLoop()

Result

wxPython ListBox

Best Regards.

Comments