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.