<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 wxpython
To make a graphycal interface to use a code in an interactive way we need a library of widgets, called wxpython.
We will explore the usage of this library mainly with examples. But to start, we have to install it with conda
Step2:  Every wxPython app is an instance of wx.App. For most simple applications you can use wx.App as is. When you get to more complex applications you may need to extend the wx.App class. The "False" parameter means "don't redirect stdout and stderr to a window".
A wx.Frame is a top-level window. The syntax is wx.Frame(Parent, Id, Title). Most of the constructors have this shape (a parent object, followed by an Id). In this example, we use None for "no parent" and wx.ID_ANY to have wxWidgets pick an id for us.
wx.TextCtrl widget
To add some text to the frame, we have to use the widget wx.TextCtrl.
By default, a text box is a single-line field, but the wx.TE_MULTILINE parameter allows you to enter multiple lines of text.
In this example, we derive from wx.Frame and overwrite its _init_ method. Here we declare a new wx.TextCtrl which is a simple text edit control. Note that since the MyFrame runs self.Show() inside its _init_ method, we no longer have to call frame.Show() explicitly.
Step3:  Status bar & Menu bar
Typically, an application has a menu and sometimes a status bar to output messages.
Notice the wx.ID_ABOUT and wx.ID_EXIT ids. These are standard ids provided by wxWidgets (see a full list at http
Step4:  Event handling
Reacting to events in wxPython is called event handling. An event is when "something" happens on your application (a button click, text input, mouse movement, etc). Much of GUI programming consists of responding to events. You bind an object to an event using the Bind() method
Step6:  Dialogs
Of course an editor is useless if it is not able to save or open documents. That's where Common dialogs come in. Common dialogs are those offered by the underlying platform so that your application will look exactly like a native application. Here is the implementation of the OnOpen method in MainWindow
Step9:  Working with Windows
In this section, we are going to present the way wxPython deals with windows and their contents, including building input forms and using various widgets/controls. We are going to build a small application that calculates the price of a quote. 
Laying out Visual Elements
Within a frame, you'll use a number of wxWindow sub-classes to flesh out the frame's contents. Here are some of the more common elements you might want to put in your frame
Step10:  The sizer.Add method has three arguments. The first one specifies the control to include in the sizer. The second one is a weight factor which means that this control will be sized in proportion to other ones. For example, if you had three edit controls and you wanted them to have the proportions 3
Step11:  The notebook
Sometimes, a form grows too big to fit on a single page. The
wx.Notebook is used in that kind of case 
Step12:  Improving the layout - using Sizers
Using absolute positioning is often not very satisfying
Step13:  wxpython and matplotlib
To use matplotlib to plot or show images in a panel, we rely on the matplotlib library.
Step14:  Let's see how this works.
python
self.figure = Figure()
initializes the top level container for all plot elements. Everything in the
plot goes within this object, just like everything in our wx application goes into
our frame!
python
self.axes = self.figure.add_subplot(111)
Our figure can contain many subplots, but here we will only make
one. add_subplot() is what does this for us. The 111 is a grid
parameter, encoded as an integer. It means 1x1 grid, first subplot. If
you want two subplots, the number would be 2x1; the first subplot
would be 211, and the second subplot would be 212.
python
self.axes.plot(t, s)
t and s are what I chose for axis values.
They are arrays that contain values that link with each other to form our plot. These arrays
must have the same size! 
This command creates and plots the t and s arrays. Since self.axes was defined as a
subplot of self.figure, this also plays a role in generating
self.figure, the container of our subplot. 
python
self.canvas = FigureCanvas(self, -1, self.figure)
Finally, we have our canvas object, which paints our object onto the
screen. Simply pass in our figure and the FigureCanvas tool does the
rest. 
Navigation toolbar
A useful toolbar is the navigation toolbar defined in matplotlib which allows one to explore the image.
Let's add to our previous example this toolbar.
Step16:  It is possible to use this navigation toolbar as a starting point to add more buttons and capabilities.
This is another example from the matplotlib demo library.
Step17:  Matplotlib examples
We give here a few more examples to show the various capabilities.
Buttons
Step18:  Check Buttons
Step19:  Cursor
Step21:  Rectangle selector
Step22:  Slider
Step24:  Span selector
Step25:  Further reading
http
<ASSISTANT_TASK:>
Python Code:
%%writefile framecode.py
#!/usr/bin/env python
import wx
app = wx.App(False)  # Create a new app, don't redirect stdout/stderr to a window.
frame = wx.Frame(None, wx.ID_ANY, "Hello World") # A Frame is a top-level window.
frame.Show(True)     # Show the frame.
app.MainLoop()
!python framecode.py
Explanation: wxpython
To make a graphycal interface to use a code in an interactive way we need a library of widgets, called wxpython.
We will explore the usage of this library mainly with examples. But to start, we have to install it with conda:
bash
conda install wxpython
A First Application: "Hello, World"
As tradition, we are first going to write a small "Hello, world" application.
End of explanation
%%writefile editor.py
#!/usr/bin/env python
import wx
class MyFrame(wx.Frame):
     We simply derive a new class of Frame. 
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.Show(True)
app = wx.App(False)
frame = MyFrame(None, 'Small editor')
app.MainLoop()
!python editor.py
Explanation: Every wxPython app is an instance of wx.App. For most simple applications you can use wx.App as is. When you get to more complex applications you may need to extend the wx.App class. The "False" parameter means "don't redirect stdout and stderr to a window".
A wx.Frame is a top-level window. The syntax is wx.Frame(Parent, Id, Title). Most of the constructors have this shape (a parent object, followed by an Id). In this example, we use None for "no parent" and wx.ID_ANY to have wxWidgets pick an id for us.
wx.TextCtrl widget
To add some text to the frame, we have to use the widget wx.TextCtrl.
By default, a text box is a single-line field, but the wx.TE_MULTILINE parameter allows you to enter multiple lines of text.
In this example, we derive from wx.Frame and overwrite its _init_ method. Here we declare a new wx.TextCtrl which is a simple text edit control. Note that since the MyFrame runs self.Show() inside its _init_ method, we no longer have to call frame.Show() explicitly.
End of explanation
%%writefile editor.py
#!/usr/bin/env python
import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar() # A Statusbar in the bottom of the window
        # Setting up the menu.
        filemenu= wx.Menu()
        # wx.ID_ABOUT and wx.ID_EXIT are standard IDs provided by wxWidgets.
        filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        filemenu.AppendSeparator()
        filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        self.Show(True)
app = wx.App(False)
frame = MainWindow(None, "Sample editor")
app.MainLoop()
!python editor.py
Explanation: Status bar & Menu bar
Typically, an application has a menu and sometimes a status bar to output messages.
Notice the wx.ID_ABOUT and wx.ID_EXIT ids. These are standard ids provided by wxWidgets (see a full list at http://docs.wxwidgets.org/2.8.12/wx_stdevtid.html). It is a good habit to use the standard ID if there is one available. This helps wxWidgets know how to display the widget in each platform to make it look more native.
End of explanation
%%writefile editor.py
#!/usr/bin/env python
import os
import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar() # A StatusBar in the bottom of the window
        # Setting up the menu.
        filemenu= wx.Menu()
        # wx.ID_ABOUT and wx.ID_EXIT are standard ids provided by wxWidgets.
        menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        # Set events.
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
        self.Show(True)
    def OnAbout(self,e):
        # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
        dlg = wx.MessageDialog( self, "A small text editor", "About Sample Editor", wx.OK)
        dlg.ShowModal() # Show it
        dlg.Destroy() # finally destroy it when finished.
    def OnExit(self,e):
        self.Close(True)  # Close the frame.
app = wx.App(False)
frame = MainWindow(None, "Sample editor")
app.MainLoop()
!python editor.py
Explanation: Event handling
Reacting to events in wxPython is called event handling. An event is when "something" happens on your application (a button click, text input, mouse movement, etc). Much of GUI programming consists of responding to events. You bind an object to an event using the Bind() method:
python
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self,parent, title=title, size=(200,100))
        ...
        menuItem = filemenu.Append(wx.ID_ABOUT, "&amp;About"," Information about this program")
        self.Bind(wx.EVT_MENU, self.OnAbout, menuItem)
This means that, from now on, when the user selects the "About" menu item, the method self.OnAbout will be executed. wx.EVT_MENU is the "select menu item" event. wxWidgets understands many other events (see the full list
at https://wiki.wxpython.org/ListOfEvents). The self.OnAbout method has the general declaration:
python
   def OnAbout(self, event):
        ...
Here event is an instance of a subclass of wx.Event. For example, a button-click event - wx.EVT_BUTTON - is a subclass of wx.Event.
The method is executed when the event occurs. By default, this method will handle the event and the event will stop after the callback finishes. However, you can "skip" an event with event.Skip(). This causes the event to go through the hierarchy of event handlers. For example:
```python
def OnButtonClick(self, event):
    if (some_condition):
        do_something()
    else:
        event.Skip()
def OnEvent(self, event):
    ...
```
When a button-click event occurs, the method OnButtonClick gets called. If some_condition is true, we do_something() otherwise we let the event be handled by the more general event handler. Now let's have a look at our application:
End of explanation
%%writefile editor.py
#!/usr/bin/env python
import os
import wx
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(200,100))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar() # A StatusBar in the bottom of the window
        # Setting up the menu.
        filemenu= wx.Menu()
        # wx.ID_ABOUT and wx.ID_EXIT are standard ids provided by wxWidgets.
        menuOpen = filemenu.Append(wx.ID_OPEN, "&Open",
                                   " Open text file")
        menuAbout = filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        # Set events.
        self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
        self.Show(True)
    def OnAbout(self,e):
        # A message dialog box with an OK button. wx.OK is a standard ID in wxWidgets.
        dlg = wx.MessageDialog( self, "A small text editor", "About Sample Editor", wx.OK)
        dlg.ShowModal() # Show it
        dlg.Destroy() # finally destroy it when finished.
    def OnExit(self,e):
        self.Close(True)  # Close the frame.
        
        
    def OnOpen(self,e):
         Open a file
        self.dirname = ''
        dlg = wx.FileDialog(self, "Choose a file", self.dirname,
                            "", "*.*", wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetFilename()
            self.dirname = dlg.GetDirectory()
            f = open(os.path.join(self.dirname, self.filename), 'r')
            self.control.SetValue(f.read())
            f.close()
        dlg.Destroy()        
app = wx.App(False)
frame = MainWindow(None, "Sample editor")
app.MainLoop()
!python editor.py
Explanation: Dialogs
Of course an editor is useless if it is not able to save or open documents. That's where Common dialogs come in. Common dialogs are those offered by the underlying platform so that your application will look exactly like a native application. Here is the implementation of the OnOpen method in MainWindow:
python
    def OnOpen(self,e):
         Open a file
        self.dirname = ''
        dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetFilename()
            self.dirname = dlg.GetDirectory()
            f = open(os.path.join(self.dirname, self.filename), 'r')
            self.control.SetValue(f.read())
            f.close()
        dlg.Destroy()
Explanation:
First, we create the dialog by calling the appropriate Constructor.
Then, we call ShowModal. That opens the dialog - "Modal" means that the user cannot do anything on the application until he clicks OK or Cancel.
The return value of ShowModal is the Id of the button pressed. If the user pressed OK we read the file.
End of explanation
%%writefile sizer_demo.py
#!/usr/bin/env python
import wx
import os
class MainWindow(wx.Frame):
    def __init__(self, parent, title):
        self.dirname=''
        # A "-1" in the size parameter instructs wxWidgets to use the default size.
        # In this case, we select 200px width and the default height.
        wx.Frame.__init__(self, parent, title=title, size=(200,-1))
        self.control = wx.TextCtrl(self, style=wx.TE_MULTILINE)
        self.CreateStatusBar() # A Statusbar in the bottom of the window
        # Setting up the menu.
        filemenu= wx.Menu()
        menuOpen = filemenu.Append(wx.ID_OPEN, "&Open"," Open a file to edit")
        menuAbout= filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
        menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
        # Creating the menubar.
        menuBar = wx.MenuBar()
        menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
        self.SetMenuBar(menuBar)  # Adding the MenuBar to the Frame content.
        # Events.
        self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
        self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
        self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
        self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
        self.buttons = []
        for i in range(0, 6):
            self.buttons.append(wx.Button(self, -1, "Button &"+str(i)))
            self.sizer2.Add(self.buttons[i], 1, wx.EXPAND)
        # Use some sizers to see layout options
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.control, 1, wx.EXPAND)
        self.sizer.Add(self.sizer2, 0, wx.EXPAND)
        #Layout sizers
        self.SetSizer(self.sizer)
        self.SetAutoLayout(1)
        self.sizer.Fit(self)
        self.Show()
    def OnAbout(self,e):
        # Create a message dialog box
        dlg = wx.MessageDialog(self, " A sample editor \n in wxPython", "About Sample Editor", wx.OK)
        dlg.ShowModal() # Shows it
        dlg.Destroy() # finally destroy it when finished.
    def OnExit(self,e):
        self.Close(True)  # Close the frame.
    def OnOpen(self,e):
         Open a file
        dlg = wx.FileDialog(self, "Choose a file", self.dirname, "", "*.*", wx.OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetFilename()
            self.dirname = dlg.GetDirectory()
            f = open(os.path.join(self.dirname, self.filename), 'r')
            self.control.SetValue(f.read())
            f.close()
        dlg.Destroy()
app = wx.App(False)
frame = MainWindow(None, "Sample editor")
app.MainLoop()
!python sizer_demo.py
Explanation: Working with Windows
In this section, we are going to present the way wxPython deals with windows and their contents, including building input forms and using various widgets/controls. We are going to build a small application that calculates the price of a quote. 
Laying out Visual Elements
Within a frame, you'll use a number of wxWindow sub-classes to flesh out the frame's contents. Here are some of the more common elements you might want to put in your frame:
- wx.MenuBar, which puts a menu bar along the top of your frame.
- wx.StatusBar, which sets up an area along the bottom of your frame for displaying status messages, etc.
- wx.ToolBar, which puts a toolbar in your frame.
- Sub-classes of wx.Control. These are objects which represent user interface widgets (ie, visual elements which display data and/or process user input). Common examples of wx.Control objects include wx.Button, wx.StaticText, wx.TextCtrl and wx.ComboBox.
- wx.Panel, which is a container to hold your various wx.Control objects. Putting your wx.Control objects inside a wx.Panel means that the user can tab from one UI widget to the next.
All visual elements (wxWindow objects and their subclasses) can hold sub-elements. Thus, for example, a wx.Frame might hold a number of wx.Panel objects, which in turn hold a number of wx.Button, wx.StaticText and wx.TextCtrl objects, giving you an entire hierarchy of elements: ￼ Note that this merely describes the way that certain visual elements are interrelated -- not how they are visually laid out within the frame. To handle the layout of elements within a frame, there are several options.
We are going to show the usage of wxSizers.
A sizer (that is, one of the wx.Sizer sub-classes) can be used to handle the visual arrangement of elements within a window or frame. Sizers can:
- Calculate an appropriate size for each visual element.
- Position the elements according to certain rules.
- Dynamically resize and/or reposition elements when a frame is resized.
Some of the more common types of sizers include:
- wx.BoxSizer, which arranges visual elements in a line going either horizontally or vertically.
- wx.GridSizer, which lays visual elements out into a grid-like structure.
- wx.FlexGridSizer, which is similar to a wx.GridSizer except that it allow for more flexibility in laying out visual elements.
A sizer is given a list of wx.Window objects to size, either by calling sizer.Add(window, options...), or by calling sizer.AddMany(...). A sizer will only work on those elements which it has been given. Sizers can be nested. That is, you can add one sizer to another sizer, for example to have two rows of buttons (each laid out by a horizontal wx.BoxSizer) contained within another wx.BoxSizer which places the rows of buttons one above the other.
Note: Notice that the above example does not lay out the six buttons into two rows of three columns each -- to do that, you should use a wxGridSizer.
In the following example we use two nested sizers, the main one with vertical layout and the embedded one with horizontal layout:
End of explanation
%%writefile example.py
import wx
class ExamplePanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        self.quote = wx.StaticText(self, label="Your quote :", 
                                   pos=(20, 30))
        # A multiline TextCtrl - This is here to show how the events work in this program, don't pay too much attention to it
        self.logger = wx.TextCtrl(self, pos=(300,20), size=(200,300), 
                                  style=wx.TE_MULTILINE | wx.TE_READONLY)
        # A button
        self.button =wx.Button(self, label="Save", pos=(200, 325))
        self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
        # the edit control - one line version.
        self.lblname = wx.StaticText(self, label="Your name :",
                                     pos=(20,60))
        self.editname = wx.TextCtrl(self, value="Enter here your name",
                                    pos=(150, 60), size=(140,-1))
        self.Bind(wx.EVT_TEXT, self.EvtText, self.editname)
        self.Bind(wx.EVT_CHAR, self.EvtChar, self.editname)
        # the combobox Control
        self.sampleList = ['friends', 'advertising', 'web search', 
                           'Yellow Pages']
        self.lblhear = wx.StaticText(self, 
                                     label="How did you hear from us ?",
                                     pos=(20, 90))
        self.edithear = wx.ComboBox(self, pos=(150, 90), size=(95, -1),
                                    choices=self.sampleList, 
                                    style=wx.CB_DROPDOWN)
        self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.edithear)
        self.Bind(wx.EVT_TEXT, self.EvtText,self.edithear)
        # Checkbox
        self.insure = wx.CheckBox(self, 
                                  label="Do you want Insured Shipment ?",
                                  pos=(20,180))
        self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.insure)
        # Radio Boxes
        radioList = ['blue', 'red', 'yellow', 'orange', 'green',
                     'purple', 'navy blue', 'black', 'gray']
        rb = wx.RadioBox(self, label="What color would you like ?",
                         pos=(20, 210), choices=radioList,
                         majorDimension=3,
                         style=wx.RA_SPECIFY_COLS)
        self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
    def EvtRadioBox(self, event):
        self.logger.AppendText('EvtRadioBox: %d\n' % event.GetInt())
    def EvtComboBox(self, event):
        self.logger.AppendText('EvtComboBox: %s\n' % event.GetString())
    def OnClick(self,event):
        self.logger.AppendText(" Click on object with Id %d\n" %event.GetId())
    def EvtText(self, event):
        self.logger.AppendText('EvtText: %s\n' % event.GetString())
    def EvtChar(self, event):
        self.logger.AppendText('EvtChar: %d\n' % event.GetKeyCode())
        event.Skip()
    def EvtCheckBox(self, event):
        self.logger.AppendText('EvtCheckBox: %d\n' % event.Checked())
%%writefile control_demo.py
import wx
from example import ExamplePanel
app = wx.App(False)
frame = wx.Frame(None,size=(500,400))
panel = ExamplePanel(frame)
frame.Show()
app.MainLoop()
!python control_demo.py
Explanation: The sizer.Add method has three arguments. The first one specifies the control to include in the sizer. The second one is a weight factor which means that this control will be sized in proportion to other ones. For example, if you had three edit controls and you wanted them to have the proportions 3:2:1 then you would specify these factors as arguments when adding the controls. 0 means that this control or sizer will not grow. The third argument is normally wx.GROW (same as wx.EXPAND) which means the control will be resized when necessary. If you use wx.SHAPED instead, the controls aspect ratio will remain the same.
If the second parameter is 0, i.e. the control will not be resized, the third parameter may indicate if the control should be centered horizontally and/or vertically by using wx.ALIGN_CENTER_HORIZONTAL, wx.ALIGN_CENTER_VERTICAL, or wx.ALIGN_CENTER (for both) instead of wx.GROW or wx.SHAPED as that third parameter.
You can alternatively specify combinations of wx.ALIGN_LEFT, wx.ALIGN_TOP, wx.ALIGN_RIGHT, and wx.ALIGN_BOTTOM. The default behavior is equivalent to wx.ALIGN_LEFT | wx.ALIGN_TOP.
One potentially confusing aspect of the wx.Sizer and its sub-classes is the distinction between a sizer and a parent window. When you create objects to go inside a sizer, you do not make the sizer the object's parent window. A sizer is a way of laying out windows, it is not a window in itself. In the above example, all six buttons would be created with the parent window being the frame or window which encloses the buttons -- not the sizer. If you try to create a visual element and pass the sizer as the parent window, your program will crash.
Once you have set up your visual elements and added them to a sizer (or to a nested set of sizers), the next step is to tell your frame or window to use the sizer. You do this in three steps:
python
window.SetSizer(sizer)
window.SetAutoLayout(True)
sizer.Fit(window)
The SetSizer() call tells your window (or frame) which sizer to use. The call to SetAutoLayout() tells your window to use the sizer to position and size your components. And finally, the call to sizer.Fit() tells the sizer to calculate the initial size and position for all its elements. If you are using sizers, this is the normal process you would go through to set up your window or frame's contents before it is displayed for the first time.
Controls
You will find a complete list of the numerous Controls that exist in wxPython in the demo and help, but here we are going to present those most frequently used:
wxButton The most basic Control: A button showing a text that you can click. For example, here is a "Clear" button (e.g. to clear a text):
python
   clearButton = wx.Button(self, wx.ID_CLEAR, "Clear")
   self.Bind(wx.EVT_BUTTON, self.OnClear, clearButton)
wxTextCtrl This control let the user input text. It generates two main events. EVT_TEXT is called whenever the text changes. EVT_CHAR is called whenever a key has been pressed.
python
    textField = wx.TextCtrl(self)
    self.Bind(wx.EVT_TEXT, self.OnChange, textField)
    self.Bind(wx.EVT_CHAR, self.OnKeyPress, textField)
For example: If the user presses the "Clear" button and that clears the text field, that will generate an EVT_TEXT event, but not an EVT_CHAR event.
wxComboBox A combobox is very similar to wxTextCtrl but in addition to the events generated by wxTextCtrl, wxComboBox has the EVT_COMBOBOX event.
wxCheckBox The checkbox is a control that gives the user true/false choice.
wxRadioBox The radiobox lets the user choose from a list of options.
Let's see an example by defining a more complex panel:
End of explanation
%%writefile notebook_demo.py
import wx
from example import ExamplePanel
app = wx.App(False)
frame = wx.Frame(None, title="Demo with Notebook",size=(500,400))
nb = wx.Notebook(frame)
nb.AddPage(ExamplePanel(nb), "Absolute Positioning")
nb.AddPage(ExamplePanel(nb), "Page Two")
nb.AddPage(ExamplePanel(nb), "Page Three")
frame.Show()
app.MainLoop()
!python notebook_demo.py
Explanation: The notebook
Sometimes, a form grows too big to fit on a single page. The
wx.Notebook is used in that kind of case : It allows the user to navigate quickly between a small amount of pages by clicking on associated tabs. We implement this by putting the wx.Notebook instead of our form into the main Frame and then add our panel into the notebook by using method AddPage.
End of explanation
%%writefile example.py
import wx
class ExamplePanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent)
        # create some sizers
        mainSizer = wx.BoxSizer(wx.VERTICAL)
        grid = wx.GridBagSizer(hgap=5, vgap=5)
        hSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.quote = wx.StaticText(self, label="Your quote: ")
        grid.Add(self.quote, pos=(0,0))
        # A multiline TextCtrl - This is here to show how the events work in this program, don't pay too much attention to it
        self.logger = wx.TextCtrl(self, size=(200,300), style=wx.TE_MULTILINE | wx.TE_READONLY)
        # A button
        self.button =wx.Button(self, label="Save")
        self.Bind(wx.EVT_BUTTON, self.OnClick,self.button)
        # the edit control - one line version.
        self.lblname = wx.StaticText(self, label="Your name :")
        grid.Add(self.lblname, pos=(1,0))
        self.editname = wx.TextCtrl(self, value="Enter here your name", size=(140,-1))
        grid.Add(self.editname, pos=(1,1))
        self.Bind(wx.EVT_TEXT, self.EvtText, self.editname)
        self.Bind(wx.EVT_CHAR, self.EvtChar, self.editname)
        # the combobox Control
        self.sampleList = ['friends', 'advertising', 'web search', 'Yellow Pages']
        self.lblhear = wx.StaticText(self, label="How did you hear from us ?")
        grid.Add(self.lblhear, pos=(3,0))
        self.edithear = wx.ComboBox(self, size=(95, -1), 
                                    choices=self.sampleList, 
                                    style=wx.CB_DROPDOWN)
        grid.Add(self.edithear, pos=(3,1))
        self.Bind(wx.EVT_COMBOBOX, self.EvtComboBox, self.edithear)
        self.Bind(wx.EVT_TEXT, self.EvtText,self.edithear)
        # add a spacer to the sizer
        grid.Add((10, 40), pos=(2,0))
        # Checkbox
        self.insure = wx.CheckBox(self, label="Do you want Insured Shipment ?")
        grid.Add(self.insure, pos=(4,0), span=(1,2), 
                 flag=wx.BOTTOM, border=5)
        self.Bind(wx.EVT_CHECKBOX, self.EvtCheckBox, self.insure)
        # Radio Boxes
        radioList = ['blue', 'red', 'yellow', 'orange', 'green', 'purple', 'navy blue', 'black', 'gray']
        rb = wx.RadioBox(self, label="What color would you like ?", pos=(20, 210), choices=radioList,  majorDimension=3,
                         style=wx.RA_SPECIFY_COLS)
        grid.Add(rb, pos=(5,0), span=(1,2))
        self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox, rb)
        hSizer.Add(grid, 0, wx.ALL, 5)
        hSizer.Add(self.logger)
        mainSizer.Add(hSizer, 0, wx.ALL, 5)
        mainSizer.Add(self.button, 0, wx.CENTER)
        self.SetSizerAndFit(mainSizer)
        
    def EvtRadioBox(self, event):
        self.logger.AppendText('EvtRadioBox: %d\n' % event.GetInt())
    def EvtComboBox(self, event):
        self.logger.AppendText('EvtComboBox: %s\n' % event.GetString())
    def OnClick(self,event):
        self.logger.AppendText(" Click on object with Id %d\n" %event.GetId())
    def EvtText(self, event):
        self.logger.AppendText('EvtText: %s\n' % event.GetString())
    def EvtChar(self, event):
        self.logger.AppendText('EvtChar: %d\n' % event.GetKeyCode())
        event.Skip()
    def EvtCheckBox(self, event):
        self.logger.AppendText('EvtCheckBox: %d\n' % event.Checked())        
%%writefile control_demo.py
import wx
from example import ExamplePanel
app = wx.App(False)
frame = wx.Frame(None,size=(500,400))
panel = ExamplePanel(frame)
frame.Show()
app.MainLoop()
!python control_demo.py
Explanation: Improving the layout - using Sizers
Using absolute positioning is often not very satisfying: The result is ugly if the windows are not (for one reason or another) the right size. WxPython has very rich vocabulary of objects to lay out controls.
- wx.BoxSizer is the most common and simple layout object but it permits a vast range of possibilities. Its role is roughly to arrange a set of controls in a line or in a row and rearrange them when needed (i.e. when the global size is changed).
- wx.GridSizer and wx.FlexGridSizer are two very important layout tools. They arrange the controls in a tabular layout.
Here is the sample above re-written to use sizers:
End of explanation
%%writefile mpl_demo.py
#!/usr/bin/env python
#import wxversion
#wxversion.ensureMinimal('2.8')
from numpy import arange, sin, pi
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as 
FigureCanvas
from matplotlib.figure import Figure
import wx
class CanvasFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1,
                          'CanvasFrame', size=(550, 350))
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0, 3.0, 0.01)
        s = sin(2 * pi * t)
        self.axes.plot(t, s)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
        self.SetSizer(self.sizer)
        self.Fit()
class App(wx.App):
    def OnInit(self):
        'Create the main window and insert the custom frame'
        frame = CanvasFrame()
        frame.Show(True)
        return True
app = App(0)
app.MainLoop()
!python mpl_demo.py
Explanation: wxpython and matplotlib
To use matplotlib to plot or show images in a panel, we rely on the matplotlib library.
End of explanation
%%writefile mpl_demo.py
#!/usr/bin/env python
import wxversion
wxversion.ensureMinimal('2.8')
from numpy import arange, sin, pi
from matplotlib.backends.backend_wxagg import \
    FigureCanvasWxAgg as FigureCanvas, \
    NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.figure import Figure
import wx
class CanvasFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1,
                          'CanvasFrame', size=(550, 350))
        self.figure = Figure()
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0, 3.0, 0.01)
        s = sin(2 * pi * t)
        self.axes.plot(t, s)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
        self.SetSizer(self.sizer)
        self.Fit()
        self.add_toolbar()  #add toolbar
    def add_toolbar(self):
        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Realize()
        # By adding toolbar in sizer, we are able to put it at the bottom
        # of the frame - so appearance is closer to GTK version.
        self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        # update the axes menu on the toolbar
        self.toolbar.update()
class App(wx.App):
    def OnInit(self):
        'Create the main window and insert the custom frame'
        frame = CanvasFrame()
        frame.Show(True)
        return True
app = App(0)
app.MainLoop()        
!python mpl_demo.py
Explanation: Let's see how this works.
python
self.figure = Figure()
initializes the top level container for all plot elements. Everything in the
plot goes within this object, just like everything in our wx application goes into
our frame!
python
self.axes = self.figure.add_subplot(111)
Our figure can contain many subplots, but here we will only make
one. add_subplot() is what does this for us. The 111 is a grid
parameter, encoded as an integer. It means 1x1 grid, first subplot. If
you want two subplots, the number would be 2x1; the first subplot
would be 211, and the second subplot would be 212.
python
self.axes.plot(t, s)
t and s are what I chose for axis values.
They are arrays that contain values that link with each other to form our plot. These arrays
must have the same size! 
This command creates and plots the t and s arrays. Since self.axes was defined as a
subplot of self.figure, this also plays a role in generating
self.figure, the container of our subplot. 
python
self.canvas = FigureCanvas(self, -1, self.figure)
Finally, we have our canvas object, which paints our object onto the
screen. Simply pass in our figure and the FigureCanvas tool does the
rest. 
Navigation toolbar
A useful toolbar is the navigation toolbar defined in matplotlib which allows one to explore the image.
Let's add to our previous example this toolbar.
End of explanation
%%writefile mpl_demo.py
#!/usr/bin/env python
import wxversion
wxversion.ensureMinimal('2.8')
from numpy import arange, sin, pi
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
from matplotlib.backends.backend_wx import _load_bitmap
from matplotlib.figure import Figure
from numpy.random import rand
import wx
class MyNavigationToolbar(NavigationToolbar2WxAgg):
    
    Extend the default wx toolbar with your own event handlers
    
    ON_CUSTOM = wx.NewId()
    def __init__(self, canvas, cankill):
        NavigationToolbar2WxAgg.__init__(self, canvas)
        # for simplicity I'm going to reuse a bitmap from wx, you'll
        # probably want to add your own.
        if 'phoenix' in wx.PlatformInfo:
            self.AddTool(self.ON_CUSTOM, 'Click me',
                         _load_bitmap('stock_left.xpm'),
                         'Activate custom contol')
            self.Bind(wx.EVT_TOOL, self._on_custom, id=self.ON_CUSTOM)
        else:
            self.AddSimpleTool(self.ON_CUSTOM, _load_bitmap('stock_left.xpm'),
                               'Click me', 'Activate custom contol')
            self.Bind(wx.EVT_TOOL, self._on_custom, id=self.ON_CUSTOM)
    def _on_custom(self, evt):
        # add some text to the axes in a random location in axes (0,1)
        # coords) with a random color
        # get the axes
        ax = self.canvas.figure.axes[0]
        # generate a random location can color
        x, y = tuple(rand(2))
        rgb = tuple(rand(3))
        # add the text and draw
        ax.text(x, y, 'You clicked me',
                transform=ax.transAxes,
                color=rgb)
        self.canvas.draw()
        evt.Skip()
class CanvasFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, -1,
                          'CanvasFrame', size=(550, 350))
        self.figure = Figure(figsize=(5, 4), dpi=100)
        self.axes = self.figure.add_subplot(111)
        t = arange(0.0, 3.0, 0.01)
        s = sin(2 * pi * t)
        self.axes.plot(t, s)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.TOP | wx.LEFT | wx.EXPAND)
        # Capture the paint message
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.toolbar = MyNavigationToolbar(self.canvas, True)
        self.toolbar.Realize()
        # By adding toolbar in sizer, we are able to put it at the bottom
        # of the frame - so appearance is closer to GTK version.
        self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
        # update the axes menu on the toolbar
        self.toolbar.update()
        self.SetSizer(self.sizer)
        self.Fit()
    def OnPaint(self, event):
        self.canvas.draw()
        event.Skip()
class App(wx.App):
    def OnInit(self):
        'Create the main window and insert the custom frame'
        frame = CanvasFrame()
        frame.Show(True)
        return True
app = App(0)
app.MainLoop()
!python mpl_demo.py
Explanation: It is possible to use this navigation toolbar as a starting point to add more buttons and capabilities.
This is another example from the matplotlib demo library.
End of explanation
%%writefile buttons_demo.py
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
freqs = np.arange(2, 20, 3)
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.2)
t = np.arange(0.0, 1.0, 0.001)
s = np.sin(2*np.pi*freqs[0]*t)
l, = plt.plot(t, s, lw=2)
class Index(object):
    ind = 0
    def next(self, event):
        self.ind += 1
        i = self.ind % len(freqs)
        ydata = np.sin(2*np.pi*freqs[i]*t)
        l.set_ydata(ydata)
        plt.draw()
    def prev(self, event):
        self.ind -= 1
        i = self.ind % len(freqs)
        ydata = np.sin(2*np.pi*freqs[i]*t)
        l.set_ydata(ydata)
        plt.draw()
callback = Index()
axprev = plt.axes([0.7, 0.05, 0.1, 0.075])
axnext = plt.axes([0.81, 0.05, 0.1, 0.075])
bnext = Button(axnext, 'Next')
bnext.on_clicked(callback.next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(callback.prev)
plt.show()
!python buttons_demo.py
Explanation: Matplotlib examples
We give here a few more examples to show the various capabilities.
Buttons
End of explanation
%%writefile checkbuttons_demo.py
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import CheckButtons
t = np.arange(0.0, 2.0, 0.01)
s0 = np.sin(2*np.pi*t)
s1 = np.sin(4*np.pi*t)
s2 = np.sin(6*np.pi*t)
fig, ax = plt.subplots()
l0, = ax.plot(t, s0, visible=False, lw=2)
l1, = ax.plot(t, s1, lw=2)
l2, = ax.plot(t, s2, lw=2)
plt.subplots_adjust(left=0.2)
rax = plt.axes([0.05, 0.4, 0.1, 0.15])
check = CheckButtons(rax, ('2 Hz', '4 Hz', '6 Hz'), (False, True, True))
def func(label):
    if label == '2 Hz':
        l0.set_visible(not l0.get_visible())
    elif label == '4 Hz':
        l1.set_visible(not l1.get_visible())
    elif label == '6 Hz':
        l2.set_visible(not l2.get_visible())
    plt.draw()
check.on_clicked(func)
plt.show()
!python checkbuttons_demo.py
Explanation: Check Buttons
End of explanation
%%writefile cursor_demo.py
#!/usr/bin/env python
from matplotlib.widgets import Cursor
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, axisbg='#FFFFCC')
x, y = 4*(np.random.rand(2, 100) - .5)
ax.plot(x, y, 'o')
ax.set_xlim(-2, 2)
ax.set_ylim(-2, 2)
# set useblit = True on gtkagg for enhanced performance
cursor = Cursor(ax, useblit=True, color='red', linewidth=2)
plt.show()
!python cursor_demo.py
Explanation: Cursor
End of explanation
%%writefile rectsel.py
#!/usr/bin/env python
Do a mouseclick somewhere, move the mouse to some destination, release
the button.  This class gives click- and release-events and also draws
a line or a box from the click-point to the actual mouseposition
(within the same axes) until the button is released.  Within the
method 'self.ignore()' it is checked wether the button from eventpress
and eventrelease are the same.
from matplotlib.widgets import RectangleSelector
import numpy as np
import matplotlib.pyplot as plt
def line_select_callback(eclick, erelease):
    'eclick and erelease are the press and release events'
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata
    print("(%3.2f, %3.2f) --> (%3.2f, %3.2f)" % (x1, y1, x2, y2))
    print(" The button you used were: %s %s" % (eclick.button, erelease.button))
def toggle_selector(event):
    print(' Key pressed.')
    if event.key in ['Q', 'q'] and toggle_selector.RS.active:
        print(' RectangleSelector deactivated.')
        toggle_selector.RS.set_active(False)
    if event.key in ['A', 'a'] and not toggle_selector.RS.active:
        print(' RectangleSelector activated.')
        toggle_selector.RS.set_active(True)
fig, current_ax = plt.subplots()                    # make a new plotingrange
N = 100000                                       # If N is large one can see
x = np.linspace(0.0, 10.0, N)                    # improvement by use blitting!
plt.plot(x, +np.sin(.2*np.pi*x), lw=3.5, c='b', alpha=.7)  # plot something
plt.plot(x, +np.cos(.2*np.pi*x), lw=3.5, c='r', alpha=.5)
plt.plot(x, -np.sin(.2*np.pi*x), lw=3.5, c='g', alpha=.3)
print("\n      click  -->  release")
# drawtype is 'box' or 'line' or 'none'
toggle_selector.RS = RectangleSelector(current_ax, line_select_callback,
                                       drawtype='box', useblit=True,
                                       button=[1, 3],  # don't use middle button
                                       minspanx=5, minspany=5,
                                       spancoords='pixels',
                                       interactive=True)
plt.connect('key_press_event', toggle_selector)
plt.show()
!python rectsel.py
Explanation: Rectangle selector
End of explanation
%%writefile slider_demo.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
fig, ax = plt.subplots()
plt.subplots_adjust(left=0.25, bottom=0.25)
t = np.arange(0.0, 1.0, 0.001)
a0 = 5
f0 = 3
s = a0*np.sin(2*np.pi*f0*t)
l, = plt.plot(t, s, lw=2, color='red')
plt.axis([0, 1, -10, 10])
axcolor = 'lightgoldenrodyellow'
axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
axamp = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)
sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0)
samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0)
def update(val):
    amp = samp.val
    freq = sfreq.val
    l.set_ydata(amp*np.sin(2*np.pi*freq*t))
    fig.canvas.draw_idle()
sfreq.on_changed(update)
samp.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
def reset(event):
    sfreq.reset()
    samp.reset()
button.on_clicked(reset)
rax = plt.axes([0.025, 0.5, 0.15, 0.15], axisbg=axcolor)
radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0)
def colorfunc(label):
    l.set_color(label)
    fig.canvas.draw_idle()
radio.on_clicked(colorfunc)
plt.show()
!python slider_demo.py
Explanation: Slider
End of explanation
%%writefile span_demo.py
#!/usr/bin/env python
The SpanSelector is a mouse widget to select a xmin/xmax range and plot the
detail view of the selected region in the lower axes
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import SpanSelector
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(211, axisbg='#FFFFCC')
x = np.arange(0.0, 5.0, 0.01)
y = np.sin(2*np.pi*x) + 0.5*np.random.randn(len(x))
ax.plot(x, y, '-')
ax.set_ylim(-2, 2)
ax.set_title('Press left mouse button and drag to test')
ax2 = fig.add_subplot(212, axisbg='#FFFFCC')
line2, = ax2.plot(x, y, '-')
def onselect(xmin, xmax):
    indmin, indmax = np.searchsorted(x, (xmin, xmax))
    indmax = min(len(x) - 1, indmax)
    thisx = x[indmin:indmax]
    thisy = y[indmin:indmax]
    line2.set_data(thisx, thisy)
    ax2.set_xlim(thisx[0], thisx[-1])
    ax2.set_ylim(thisy.min(), thisy.max())
    fig.canvas.draw()
# set useblit True on gtkagg for enhanced performance
span = SpanSelector(ax, onselect, 'horizontal', useblit=True,
                    rectprops=dict(alpha=0.5, facecolor='red'))
plt.show()
!python span_demo.py
Explanation: Span selector
End of explanation
%load_ext version_information
%version_information wxpython
Explanation: Further reading
http://t2mh.com/python/wxPython%20in%20Action%20(2006).pdf
https://www.tutorialspoint.com/wxpython/wxpython_tutorial.pdf
Versions
End of explanation
<END_TASK>