This page contains an example of a window with a tree and a splitter window. The example is based on the wx.TreeCtrl example in AnotherTutorial.

wx.TreeCtrl with a wx.SplitterWindow

The wx.TreeCtrl class provides a widget for displaying data in a tree-like structure. In this little example we extend the wx.TreeCtrl example in the AnotherTutorial tutorial and add a splitter window. This type of layout can be useful if you are considering writing a GUI file-transfer application.

   1 #!/usr/bin/env python
   2 # treectrlwithsplitter.py
   3 
   4 import wx
   5 
   6 class MyTree(wx.TreeCtrl):
   7     '''Our customized TreeCtrl class
   8     '''
   9     def __init__(self, parent, id, position, size, style):
  10         '''Initialize our tree
  11         '''
  12         wx.TreeCtrl.__init__(self, parent, id, position, size, style)
  13         root = self.AddRoot('Programmer')
  14         os = self.AppendItem(root, 'Operating Systems')
  15         pl = self.AppendItem(root, 'Programming Languages')
  16         tk = self.AppendItem(root, 'Toolkits')
  17         self.AppendItem(os, 'Linux')
  18         self.AppendItem(os, 'FreeBSD')
  19         self.AppendItem(os, 'OpenBSD')
  20         self.AppendItem(os, 'NetBSD')
  21         self.AppendItem(os, 'Solaris')
  22         cl = self.AppendItem(pl, 'Compiled languages')
  23         sl = self.AppendItem(pl, 'Scripting languages')
  24         self.AppendItem(cl, 'Java')
  25         self.AppendItem(cl, 'C++')
  26         self.AppendItem(cl, 'C')
  27         self.AppendItem(cl, 'Pascal')
  28         self.AppendItem(sl, 'Python')
  29         self.AppendItem(sl, 'Ruby')
  30         self.AppendItem(sl, 'Tcl')
  31         self.AppendItem(sl, 'PHP')
  32         self.AppendItem(tk, 'Qt')
  33         self.AppendItem(tk, 'MFC')
  34         self.AppendItem(tk, 'wxPython')
  35         self.AppendItem(tk, 'GTK+')
  36         self.AppendItem(tk, 'Swing')
  37 
  38 class MyFrame(wx.Frame):
  39     '''Our customized window class
  40     '''
  41     def __init__(self, parent, id, title):
  42         '''Initialize our window
  43         '''
  44         wx.Frame.__init__(self, parent, id, title,
  45                           wx.DefaultPosition, wx.Size(450, 350))
  46 
  47         # Create a splitter window
  48         self.splitter = wx.SplitterWindow(self, -1)
  49 
  50         # Create the left panel
  51         leftPanel = wx.Panel(self.splitter, -1)
  52         # Create a box sizer that will contain the left panel contents
  53         leftBox = wx.BoxSizer(wx.VERTICAL)
  54 
  55         # Create our tree and put it into the left panel
  56         self.tree = MyTree(leftPanel, 1, wx.DefaultPosition, (-1, -1),
  57                            wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS)
  58 
  59         # Add the tree to the box sizer
  60         leftBox.Add(self.tree, 1, wx.EXPAND)
  61 
  62         # Bind the OnSelChanged method to the tree
  63         self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)
  64 
  65         # Set the size of the right panel to that required by the tree
  66         leftPanel.SetSizer(leftBox)
  67 
  68         # Create the right panel
  69         rightPanel = wx.Panel(self.splitter, -1)
  70         # Create the right box sizer that will contain the panel's contents
  71         rightBox = wx.BoxSizer(wx.VERTICAL)
  72         # Create a widget to display static text and store it in the right
  73         # panel
  74         self.display = wx.StaticText(rightPanel, -1, '', (10, 10),
  75                                      style=wx.ALIGN_CENTRE)
  76         # Add the display widget to the right panel
  77         rightBox.Add(self.display, -1, wx.EXPAND)
  78         # Set the size of the right panel to that required by the
  79         # display widget
  80         rightPanel.SetSizer(rightBox)
  81         # Put the left and right panes into the split window
  82         self.splitter.SplitVertically(leftPanel, rightPanel)
  83         # Create the window in the centre of the screen
  84         self.Centre()
  85 
  86     def OnSelChanged(self, event):
  87         '''Method called when selected item is changed
  88         '''
  89         # Get the selected item object
  90         item =  event.GetItem()
  91         # Display the selected item text in the text widget
  92         self.display.SetLabel(self.tree.GetItemText(item))
  93 
  94 class MyApp(wx.App):
  95     '''Our application class
  96     '''
  97     def OnInit(self):
  98         '''Initialize by creating the split window with the tree
  99         '''
 100         frame = MyFrame(None, -1, 'treectrl.py')
 101         frame.Show(True)
 102         self.SetTopWindow(frame)
 103         return True
 104 
 105 if __name__ == '__main__':
 106     app = MyApp(0)
 107     app.MainLoop()

In this example we have created a customized TreeCtrl class called MyTreeCtrl by sub-classing wx.TreeCtrl and placing all our tree-specific setup into this class. This makes the application a tiny, little bit neater than including everything in our customized window class.

In our MyTreeCtrl class the __init__ method first invokes the __init__ method of the wx.TreeCtrl base class:

wx.TreeCtrl.__init__(self, parent, id, position, size, style)

You ought to call the base-class constructor before you start to define the widget as you may need some initialized base-class methods or attributes in your class.

We then create the root node of the tree:

root = self.AddRoot('Programmer')

and add nodes to the root node:

os = self.AppendItem(root, 'Operating Systems')
pl = self.AppendItem(root, 'Programming Languages')
tk = self.AppendItem(root, 'Toolkits')

We can then add leaves to a node under the root node:

self.AppendItem(os, 'Linux')
self.AppendItem(os, 'FreeBSD')
self.AppendItem(os, 'OpenBSD')
self.AppendItem(os, 'NetBSD')
self.AppendItem(os, 'Solaris')

The class myFrame is our tailored window and will contain the widget to display a tree and a widget to display a select tree item and these widgets will be separated by a moveable splitter.

The class sub-classes the wx.Frame class and we call the __init__ method of the base class wx.Frame in our __init__ method:

wx.Frame.__init__(self, parent, id, title,
                          wx.DefaultPosition, wx.Size(450, 350))

We then create a splitter window widget:

self.splitter = wx.SplitterWindow(self, -1)

and create a container widget (a panel) in the splitter:

leftPanel = wx.Panel(self.splitter, -1)

We also need to create a sizer to size correctly all the widgets we place into the panel:

leftBox = wx.BoxSizer(wx.VERTICAL)

Now that we have the sizers and the container widget we create a tree widget by invoking our class:

self.tree = MyTree(leftPanel, 1, wx.DefaultPosition, (-1, -1),
                           wx.TR_HIDE_ROOT|wx.TR_HAS_BUTTONS)

We create the tree widget in our panel and place it in the default position. We don't specify the size of the widget (we will let the sizer define that). We also set the flags to hide the root node and display the widget with toggle buttons.

We then add the tree widget to the sizer and ask it to use up as much space in the container as possible:

leftBox.Add(self.tree, 1, wx.EXPAND)

We also bind the method OnSelChanged to the widget which will be invoked whenever we select a different element:

self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.OnSelChanged, id=1)

We then let the box sizer set the size of the panel:

leftPanel.SetSizer(leftBox)

Now we're done with the left panel containing the tree widget. We now want to create a right panel that will contain the selected element. First, we create another panel container in the splitter window:

rightPanel = wx.Panel(self.splitter, -1)

and we create a box sizer for the panel to correctly size the panel widgets:

rightBox = wx.BoxSizer(wx.VERTICAL)

We then create a widget in the panel to display the selected item:

self.display = wx.StaticText(rightPanel, -1, '', (10, 10),
                                     style=wx.ALIGN_CENTRE)

We add the text widget to the sizer and ask it to use up as much space as possible:

rightBox.Add(self.display, -1, wx.EXPAND)

We let the box sizer set the size of the panel:

rightPanel.SetSizer(rightBox)

and we add the two panels to the splitter window:

self.splitter.SplitVertically(leftPanel, rightPanel)

Finally, we make sure the window is created in the centre of our screen:

self.Centre()

The OnSelChanged method is invoked whenever a different tree element is selected.

item =  event.GetItem()
self.display.SetLabel(self.tree.GetItemText(item))

The event object holds information on which item was selected and we extract the item object and write the text to the static text widget.

Our MyApp class subclasses the wx.App to create our customized application. We override the OnInit method and create our window containing the tree and text widgets separated by a moveable splitter window:

frame = MyFrame(None, -1, 'treectrl.py')
frame.Show(True)
self.SetTopWindow(frame)
return True

Running the application should result in the following window being displayed.

[ATTACH]

AnotherTutorialTreeCtrlComment (last edited 2008-04-07 16:59:20 by mimosait)

NOTE: To edit pages in this wiki you must be a member of the TrustedEditorsGroup.