from IPython.display import Image
Image(filename='Figs_ipandcg_2014/2014_Session_1.png')
In this exercise you will learn how to build simple application with Graphical User Interface (GUI). For this purpose wxPython libraries will be used. Presented examples base on the on-line tutorial.
In the cell below we import all needed packages.
import numpy as np
from scipy import misc
from IPython.display import Image
import matplotlib.pyplot as plt
In the first task create an empty, blank window, as you can see at the figure below. To get more information see example.
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/1_empty_window.png")
The source code is listed belove followes. There is an IPython magic command %reset in the first line. It should be added only wehen you are using IPython notebook as you editor. If case of regular Python script (with .py extention) this line is optional and can be omitted. It is (strongly) reccomended to use regular script while practicing with wxPython library.
%reset
# Empty window
#!/usr/bin/python
# simple.py
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'simple.py')
frame.Show()
app.MainLoop()
To get help with Keyboard Shortcuts of IPython notebook press "Ctrl+m h". Practice how to add, remove, delete and execute a new cell. You can turn on/off line numbers inside cell with the use of "Ctrl+m l" keys sequence.
To the existing window add a control to display text (wxStaticText). Place it in the center of the window. Change background color; use different manners of setting couour(use wx.Frame.SetBackgroundColour() function and wx.Colour class and String). Explain each line of the source code.
%reset
import wx
app = wx.App()
frame = wx.Frame(None, -1, 'Name :D')
#frame.SetBackgroundColour(wx.Colour(255,255,255))
#frame.SetBackgroundColour((255,100,55))
frame.SetBackgroundColour("Red")
frame.Show()
text = wx.StaticText(frame, -1, "Some text ;-)",(110,50))
#text.Center()
app.MainLoop()
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/1a_empty_window_modification.png")
Based on tutorial write an application that contains three buttons. Use booth methods for layout your widgets:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/2_buttons_manual.png")
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/2_buttons_sizers.png")
Remember! To get help use "?" mark
Use help and explain meaning of each line. What is the result when the window size is changed?
%reset
#!/usr/bin/python
# layout.py
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition)
panel = wx.Panel(self, -1)
wx.Button(panel, 1, "Button1", (0,0))
wx.Button(panel, 2, "Button2", (80,0))
wx.Button(panel, 3, "Button3", (180,0))
self.SetSize((300,100))
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'layout.py')
frame.Show(True)
frame.Centre()
return True
app = MyApp(0)
app.MainLoop()
Based on tutorial observe and explain how to bind any action with your buttons.
Write this piece of code in the regular Python script.
%reset
#!/usr/bin/python
# layout.py
import wx
import numpy as np
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition)
panel = wx.Panel(self, -1)
wx.Button(panel, 1, "Button1", (0,0))
wx.Button(panel, 2, label="Button2", pos=(80,0))
wx.Button(panel, id=3, label="Button3", pos=(180,0))
self.SetSize((300,100))
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=1)
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=2)
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=3)
def OnPrint(self,event):
#print 'button nr.', event.GetId()
#print event.GetEventObject().GetLabel()
event.GetEventObject().SetBackgroundColour(np.random.random_integers(0,255,3))
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'layout.py')
frame.Show(True)
frame.Centre()
return True
app = MyApp(0)
app.MainLoop()
Check the usage of function random.random_integers from numpy package.
np.random.random_integers(0,10,3)
For volunteers: plaease find a very nice tutorial on sizers.
Use help and explain meaning of each line and every parameter. What is happend when the window size is changed?
% reset
#!/usr/bin/python
# wxboxsizer.py
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(250, 50))
panel = wx.Panel(self, -1)
box = wx.BoxSizer(wx.HORIZONTAL)
self.button1 = wx.Button(panel, id=wx.ID_ANY, label='Button nr 1')
self.button2 = wx.Button(panel, id=wx.ID_ANY, label='Button 2')
self.button3 = wx.Button(panel, id=wx.ID_ANY, label='Button 3 - very long name')
box.Add(self.button1, 0, wx.EXPAND | wx.ALL, border=5 )
box.Add(self.button2, 1, wx.EXPAND | wx.ALL, border=15 )
box.Add(self.button3, 2, wx.EXPAND | wx.ALL, border=5 )
panel.SetSizer(box)
self.Centre()
self.Fit()
self.Layout()
self.SetSize((400,100))
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'wxboxsizer.py')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
Write this piece of code in the Python regular script. Explain how it works.
% reset
#!/usr/bin/python
# wxboxsizer.py
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, (-1, -1), wx.Size(250, 50))
panel = wx.Panel(self, -1)
box = wx.BoxSizer(wx.HORIZONTAL)
self.button1 = wx.Button(panel, id=wx.ID_ANY, label='Button nr 1')
self.button2 = wx.Button(panel, id=wx.ID_ANY, label='Button 2')
self.button3 = wx.Button(panel, id=wx.ID_ANY, label='Button 3 - very long name')
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button1.GetId())
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button2.GetId())
self.Bind(wx.EVT_BUTTON, self.OnPrint, id=self.button3.GetId())
box.Add(self.button1, 0, wx.EXPAND | wx.ALL, border=5 )
box.Add(self.button2, 1, wx.EXPAND | wx.ALL, border=15 )
box.Add(self.button3, 2, wx.EXPAND | wx.ALL, border=5 )
panel.SetSizer(box)
self.Centre()
#self.Fit()
#self.Layout()
self.SetSize((400,100))
def OnPrint(self, event):
if event.GetId() == self.button1.GetId():
print 'pressed button 1'
elif event.GetId() == self.button2.GetId():
print 'pressed button 2'
elif event.GetId() == self.button3.GetId():
print 'pressed button 3'
else:
print 'pressed some other button'
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, 'wxboxsizer.py')
frame.Show(True)
return True
app = MyApp(0)
app.MainLoop()
In this section it is showed how to glue together numpy, matplotlib and wxPython librares in order to dispaly a image (array).
Let's load image into memory and print some of its parameters (minimum, maximum and average value).
from matplotlib.pyplot import imread, imshow
image = imread('images_2014/brain.bmp')
print image.min(), image.max(), image.mean() ,image.shape
To display image with the use of imshow() function from matplotlib library write line:
imshow(image, cmap='gray')
The sorce code of the application that enables to display image inside window of wxPython is as follows:
%reset
import wx
import numpy as np
from matplotlib.figure import Figure
from matplotlib.pyplot import imread
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
class DisplayImage(wx.Frame):
def __init__(self,parent,image):
self.img = image
wx.Frame.__init__(self, parent, title="Brain", size=(wx.GetClientDisplayRect()[2], wx.GetClientDisplayRect()[3]) )
self.CreatePanel()
self.DrawFigure()
def CreatePanel(self):
self.fig = Figure()
self.fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
self.canvas = FigCanvas(self, -1, self.fig)
self.axes = self.fig.add_subplot(111)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.hbox = wx.BoxSizer(wx.VERTICAL) #main siezer
self.hbox.Add(self.canvas, 1, wx.EXPAND | wx.ALL,1)
self.SetSizer(self.hbox)
self.SetAutoLayout(True)
self.Fit()
def DrawFigure(self):
self.axes.clear()
self.imshow = self.axes.imshow(self.img,cmap="gray")
self.canvas.draw()
image = imread('2014_Session_1-2-3_images_for_students/brain.bmp')
app = wx.App(False)
img = DisplayImage(None,image)
img.Show()
app.MainLoop()
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/3_display_brain.png")
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/4_threshold_brain.png")
def thresh1(im, th=125):
img = im.copy()
for y in range(img.shape[0]):
for x in range(img.shape[1]):
if img[y,x] >= th:
img[y,x]= 255
else:
img[y,x] = 0
return img
img_th1 = thresh1(image, th=50)
plt.imshow(img_th1, plt.cm.gray)
def thresh2(im, th=100):
img = im.copy()
img[img>=th] = 255
img[img<th] = 0
return img
img_th2 = thresh2(image, th=125)
plt.imshow(img_th2, plt.cm.gray)
th = 155
img_th3 = np.where(image>th, 255, 0)
plt.imshow(img_th3, plt.cm.gray)
In this task ones have to add additional widgets (GUI elemetns) to our window. We will broaden our application by additional slider to do thresholding.
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/4_threshold_brain_slider.png")
%reset
import wx
import numpy as np
from scipy import misc
from matplotlib.pyplot import imread
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
class imageShow(wx.Frame):
def __init__(self,parent,image):
self.img = image
wx.Frame.__init__(self, parent, title="Brain", size=(wx.GetClientDisplayRect()[2], wx.GetClientDisplayRect()[3]) )
self.CreatePanel()
self.DrawFigure()
def CreatePanel(self):
self.fig = Figure()
self.fig.subplots_adjust(left=0.01, right=0.99, top=0.99, bottom=0.01)
self.canvas = FigCanvas(self, -1, self.fig)
self.axes = self.fig.add_subplot(111)
self.axes.get_xaxis().set_visible(False)
self.axes.get_yaxis().set_visible(False)
self.slider1 = wx.Slider(self,id=wx.ID_ANY, value=125,minValue=0,maxValue=255,style=wx.SL_AUTOTICKS|wx.SL_HORIZONTAL|wx.SL_LABELS)
self.Bind(wx.EVT_SLIDER, self.OnSlider)
self.hbox = wx.BoxSizer(wx.VERTICAL) #main siezer
self.hbox.Add(self.canvas, 1, wx.EXPAND | wx.ALL,1)
self.hbox.Add(self.slider1,0.5, wx.EXPAND | wx.ADJUST_MINSIZE |wx.ALL, 1)
self.SetSizer(self.hbox)
self.SetAutoLayout(True)
self.Fit()
def OnSlider(self,event):
self.DrawFigure()
def DrawFigure(self, minn = 0, maxx = 255):
self.axes.clear()
self.imshow = self.axes.imshow(np.where(self.img>self.slider1.GetValue(),255,0), cmap='gray')
self.canvas.draw()
image = imread('2014_Session_1-2-3_images_for_students/brain.bmp')
app = wx.App(False)
img = imageShow(None,image)
img.Show()
app.MainLoop()
Create new script that allows the manipulation of the text. There should be a special place to enter a text (wx.TextCtrl) and function keys shown below:
from IPython.display import Image
Image(filename="Figs_ipandcg_2014/5_text_manipulation.png")