| | |
Starting wxPython (GUI code)
![]() |
Sizers look a little complex at first, but they can make your component layouts a lot simpler. The wx.GridSizer() is particularly well suited for a bunch of similar widgets generated with a for loop. In this case I used the gridsizer for the buttons of a simple calculator. The buttons simply keep wrapping from left to right, down a notch then left to right again ...
python Syntax (Toggle Plain Text)
# create a calulator button layout with wx.GridSizer() # then add a few things to form a tiny wxPython calculator import wx class MyFrame(wx.Frame): """make a frame, inherits wx.Frame""" def __init__(self): # create a frame/window, no parent wx.Frame.__init__(self, None, wx.ID_ANY, 'wx_Calc', pos=(300, 150), size=(185, 160)) self.SetBackgroundColour('green') # main sizer vsizer = wx.BoxSizer(wx.VERTICAL) self.edit = wx.TextCtrl(self, -1, value="", size=(165, 20)) # follows layout of calculator keys self.btn_list = [ '7', '8', '9', '/', 'c', '4', '5', '6', '*', 'bs', '1', '2', '3', '-', '**', '0', '.', '=', '+', 'neg' ] # wx.GridSizer(rows, cols, vgap, hgap) gsizer = wx.GridSizer(4, 5, 2, 2) self.btn = range(len(self.btn_list)) for ix, b_label in enumerate(self.btn_list): # set up a consecutive unique id for each button id = 1000 + ix self.btn[ix] = wx.Button(self, id, label=b_label, size=(20, 20)) # the gridsizer fills left to right one row at a time gsizer.Add(self.btn[ix], 0, wx.ALL|wx.EXPAND, border=2) self.btn[ix].Bind(wx.EVT_BUTTON, self.btnClick) # now add the whole thing to the main sizer and set it vsizer.Add(self.edit, 0, wx.EXPAND) vsizer.Add(gsizer, 0, wx.EXPAND) self.SetSizer(vsizer) def btnClick(self, event): # get the label of the button clicked label = self.btn_list[event.GetId() - 1000] e_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '*', '/', '**', '.'] if label in e_list: self.edit.SetValue(self.edit.GetValue() + label) elif label == 'neg': # negate, note eval() takes care of double negate self.edit.SetValue('-' + self.edit.GetValue()) elif label == 'c': # clear self.edit.SetValue('') elif label == 'bs': # backspace self.edit.SetValue(self.edit.GetValue()[:-1]) elif label == '=': str1 = self.edit.GetValue() # prevent folks from being nasty with eval() if not str1 or str1[0] not in '0123456789-+.': self.edit.SetValue('unrecognized operation') return while str1[0] == '0': # avoid leading zero (octal) error with eval() str1 = str1[1:] if '/' in str1 and '.' not in str1: # turn into floating point division str1 = str1 + '.0' try: self.edit.SetValue(str(eval(str1))) except ZeroDivisionError: self.edit.SetValue('division by zero error') else: self.edit.SetValue('unrecognized operation') app = wx.App(0) # create MyFrame instance and show the frame MyFrame().Show() app.MainLoop()
May 'the Google' be with you!
I was playing around with wxPython's slider widget and found a nice application for it:
python Syntax (Toggle Plain Text)
# use slider inputs to calculate cost of petrol in the USA and Europe import wx class MyFrame(wx.Frame): def __init__(self, parent, mytitle, mysize): wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle, size=mysize) self.SetBackgroundColour("yellow") # create input widgets # label for slider1 label_s1 = wx.StaticText(self, wx.ID_ANY, "US cents per US Gallon:") # can only use integer values!!! # initial value = 450, min value = 300, max value = 600 self.slider1 = wx.Slider(self, wx.ID_ANY, 450, 300, 600, size=(320, 40), style=wx.SL_HORIZONTAL|wx.SL_LABELS) # label for slider2 label_s2 = wx.StaticText(self, wx.ID_ANY, "Euro cents per Liter:") # initial value = 150, min value = 100, max value = 200 self.slider2 = wx.Slider(self, wx.ID_ANY, 150, 100, 200, size=(320, 40), style=wx.SL_HORIZONTAL|wx.SL_LABELS) # label for slider3 label_s3 = wx.StaticText(self, wx.ID_ANY, "US cents per Euro:") # initial value = 160, min value = 100, max value = 200 self.slider3 = wx.Slider(self, wx.ID_ANY, 160, 100, 200, size=(320, 40), style=wx.SL_HORIZONTAL|wx.SL_LABELS) # bind all mouse slider marker drags to the same action self.Bind(wx.EVT_SLIDER, self.onAction) # create an output widget self.label = wx.StaticText(self, wx.ID_ANY, "") # use a vertical boxsizer for the widget placement sizer_v = wx.BoxSizer(wx.VERTICAL) sizer_v.Add(label_s1, 0, flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=10) sizer_v.Add(self.slider1, 0, flag=wx.ALL|wx.EXPAND, border=5) sizer_v.Add(label_s2, 0, flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=10) sizer_v.Add(self.slider2, 0, flag=wx.ALL|wx.EXPAND, border=5) sizer_v.Add(label_s3, 0, flag=wx.LEFT|wx.RIGHT|wx.EXPAND, border=10) sizer_v.Add(self.slider3, 0, flag=wx.ALL|wx.EXPAND, border=5) sizer_v.Add(self.label, 0, flag=wx.ALL|wx.EXPAND, border=10) self.SetSizer(sizer_v) # show opening result self.onAction(None) def onAction(self, event): """ some action code""" s = "The result ... \n\n" # gives integer cents values, convert to $ and Euro us_price = self.slider1.GetValue()/100.0 euro_price = self.slider2.GetValue()/100.0 euro_cost = self.slider3.GetValue()/100.0 # 1 US gal = 3.785 liters s1 = "In the USA $%.2f/gal = $%.2f/liter = %.2f Euro/liter\n" % \ (us_price, us_price/3.785, us_price/(3.785*euro_cost)) s2 = "In Europe $%.2f/gal = $%.2f/liter = %.2f Euro/liter" % \ (euro_price*euro_cost*3.785, euro_price*euro_cost, euro_price) self.label.SetLabel(s + s1 + s2) app = wx.App() # create the MyFrame instance and then show the frame MyFrame(None, 'The petrol sliders', (350, 300)).Show() app.MainLoop()
No one died when Clinton lied.
A nice looking informative about-box is easy to achieve with the wx.AboutBox() widget. The example also touches on menu construction and wxPython's wordwrap feature:
python Syntax (Toggle Plain Text)
# testing the fancy wx.AboutBox() widget import wx from wx.lib.wordwrap import wordwrap class MyFrame(wx.Frame): """ create a frame, with a menu, statusbar and 2 about dialogs """ def __init__(self): # create a frame/window, no parent, default to wxID_ANY wx.Frame.__init__(self, None, wx.ID_ANY, "wx.AboutBox test", pos=(300, 150), size=(300, 350)) self.SetBackgroundColour("brown") # create a status bar at the bottom self.CreateStatusBar() self.SetStatusText("Click on File") menu = wx.Menu() # the optional & allows you to use alt/a # the last string argument shows in the status bar on mouse_over menu_about = menu.Append(wx.ID_ANY, "&About", "Ho-hum about box") menu_about2 = menu.Append(wx.ID_ANY, "About&2", "Fancy about box") menu.AppendSeparator() # the optional & allows you to use alt/x menu_exit = menu.Append(wx.ID_ANY, "E&xit", "Quit the program") # create a menu bar at the top menuBar = wx.MenuBar() # the & allows you to use alt/f menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) # bind the menu events to an action/function/method self.Bind(wx.EVT_MENU, self.onMenuAbout, menu_about) self.Bind(wx.EVT_MENU, self.onMenuAbout2, menu_about2) self.Bind(wx.EVT_MENU, self.onMenuExit, menu_exit) def onMenuAbout(self, event): """a somewhat ho-hum about box""" dlg = wx.MessageDialog(self, "a simple application using wxFrame, wxMenu\n" "a statusbar, and this about message.", "About", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() def onMenuAbout2(self, event): """use the much fancier wx.AboutBox()""" # first fill the info object info = wx.AboutDialogInfo() info.Name = "Bratwurst7" info.Version = "v.1.7.4" info.Copyright = "(C) copyfight 2008" info.Description = wordwrap( "The Bratwurst7 program is a software program that " "makes you desire a freshly grilled bratwurst and " "a good German beer right now! Teaching programmers " "everywhere to be aware of those hidden immediate " "inner desires!", 300, wx.ClientDC(self)) info.WebSite = ("http://en.wikipedia.org/wiki/Bratwurst", "Bratwurst7 home") info.Developers = ["Carl Arm", "Carol Bein", "Candy Kisser"] info.License = "Wish upon a star!" # now call wx.AboutBox with this info object wx.AboutBox(info) def onMenuExit(self, event): self.Close(True) app = wx.App() # create the MyFrame class instance, then show the frame MyFrame().Show() app.MainLoop()
No one died when Clinton lied.
Some light wxPython stuff. The first example shows you how to bring in your own icon in the title of a frame:
The second example uses the wx.EVT_SIZE event to respond to changes in the size of the frame:
python Syntax (Toggle Plain Text)
# set the icon of a wx.Frame() import wx app = wx.App(0) frame = wx.Frame(None, wx.ID_ANY, title='Set A New Icon') # pick an icon image file you have ... frame.SetIcon(wx.Icon('py.ico', wx.BITMAP_TYPE_ICO)) frame.Center() frame.Show() app.MainLoop()
python Syntax (Toggle Plain Text)
# use the wx.EVT_SIZE event to show the frame size # the title itself may take up 34 pixels of the height import wx class MyFrame(wx.Frame): def __init__(self, parent): # use default size and position wx.Frame.__init__(self, parent, wx.ID_ANY) self.SetBackgroundColour("yellow") wx.StaticText(self, wx.ID_ANY, "change the size of the frame", (5,5)) # respond to changes in the size of the frame self.Bind(wx.EVT_SIZE, self.onSize) def onSize(self, event): """display the current frame size in the title""" self.SetTitle(str(event.GetSize())) # eg. (400, 489) app = wx.App(0) # create a MyFrame instance and show the frame MyFrame(None).Show() app.MainLoop()
Never argue with idiots, they'll just bring you down to their level and beat you with their experience.
Some heavier wxPython stuff. I was playing around with the wx.ListCtrl() widget, and it took me quite a while to find a way to get a hold of the selected row. Here is a short example of the solution:
python Syntax (Toggle Plain Text)
# exploring wxPython's # wx.ListCtrl(parent, id, pos, size, style) # a fancier list box with a lot of mix-in options # some of the styles = # wxLC_REPORT report mode # wxLC_HRULES draws horizontal rules between rows in report mode # wxLC_VRULES draws vertical rules between columns in report mode. import wx class MyFrame(wx.Frame): def __init__(self, parent, data): # use default size and position wx.Frame.__init__(self, parent, wx.ID_ANY, 'Test the wx.ListCtrl()', size=(400, 220)) self.SetBackgroundColour("yellow") # make data available to the instance self.data = data # create the list control self.lc = wx.ListCtrl(self, wx.ID_ANY, size=(-1, 120), style=wx.LC_REPORT|wx.SUNKEN_BORDER|wx.LC_HRULES) # select an item (left mouse click on it) and bind to an action self.lc.Bind(wx.EVT_LIST_ITEM_SELECTED,self.onAction) self.loadList() # create an output widget self.label = wx.StaticText(self, wx.ID_ANY, "Select a name") # use a vertical boxsizer for the widget placement sizer_v = wx.BoxSizer(wx.VERTICAL) sizer_v.Add(self.lc, 1, flag=wx.ALL|wx.EXPAND, border=10) sizer_v.Add(self.label, 0, flag=wx.ALL|wx.EXPAND, border=10) self.SetSizer(sizer_v) def loadList(self): # first the columns with header titles self.lc.InsertColumn(0,"Name") self.lc.SetColumnWidth(0, 200) self.lc.InsertColumn(1,"Age",wx.LIST_FORMAT_RIGHT) self.lc.InsertColumn(2,"Weight",wx.LIST_FORMAT_RIGHT) # now each data row for key, val in self.data.items(): # set max_rows, change if need be max_rows = 1000 # also sets/updates row index starting at 0 index = self.lc.InsertStringItem(max_rows, val[0]) self.lc.SetStringItem(index, 1, val[1]) self.lc.SetStringItem(index, 2, val[2]) # needed by GetItemData() self.lc.SetItemData(index, key) def onAction(self, event): """ some action code""" # -1 --> get the first item that matches the specified flags # wx.LIST_NEXT_ALL search for subsequent item by index # wx.LIST_STATE_SELECTED get the selected item ix_selected = self.lc.GetNextItem(item=-1, geometry=wx.LIST_NEXT_ALL, state=wx.LIST_STATE_SELECTED) # get the value of the key in dictionary self.data data_value = self.data[self.lc.GetItemData(ix_selected)] # pick the name (first item in the value tuple) name = ' --> ' + data_value[0] self.label.SetLabel(str(data_value) + name) # data to load the listctrl in the form of a dictionary # the header is ('Name', 'Age', 'Weight') data = { 1 : ('Heidi Kalumpa', '36', '127'), 2 : ('Frank Maruco', '27', '234'), 3 : ('Larry Pestraus', '19', '315'), 4 : ('Serge Romanowski', '59', '147'), 5 : ('Carolus Arm', '94', '102'), 6 : ('Michel Sargnagel', '21', '175') } app = wx.App(0) # create a MyFrame instance and then show the frame MyFrame(None, data).Show() app.MainLoop()
Last edited by ZZucker; Jul 18th, 2008 at 1:38 pm.
Never argue with idiots, they'll just bring you down to their level and beat you with their experience.
This might be the simplest way to display an image from a file using the wxPython GUI toolkit:
What the heck, lets make it even simpler:
python Syntax (Toggle Plain Text)
# simplest way to show an image from a file with wxPython import wx app = wx.App(0) frame = wx.Frame(None, -1, "Show an image file") # pick an image file you have in the working folder # (can be a .jpg, .png, ,gif, .bmp image file) image_file = 'clouds.jpg' # create an internal image image = wx.Bitmap(image_file) # show the image as static bitmap wx.StaticBitmap(frame, -1, image) frame.Show() app.MainLoop()
python Syntax (Toggle Plain Text)
import wx app = wx.App(0) frame = wx.Frame(None, -1, "Show an image file") wx.StaticBitmap(frame, -1, wx.Bitmap('clouds.jpg')) frame.Show() app.MainLoop()
Last edited by ZZucker; Jul 18th, 2008 at 2:11 pm.
Never argue with idiots, they'll just bring you down to their level and beat you with their experience.
In a previous example we have learned how to create a wxPython canvas and draw shapes on it. If you want to save your artistic creation to one of the common image files, you have to create the canvas on top of a blank bitmap. Here is an example ...
python Syntax (Toggle Plain Text)
# create a canvas on top of a blank bitmap # this allows to save any canvas drawings # created to a standard image file import wx class MyFrame(wx.Frame): def __init__(self, parent=None, id=-1, title=None): wx.Frame.__init__(self, parent, id, title) self.statbmp = wx.StaticBitmap(self) self.draw_image() self.save_image() def draw_image(self): # select the width and height of the blank bitmap w, h = 340, 340 # create the blank bitmap as a draw background draw_bmp = wx.EmptyBitmap(w, h) # create the canvas on top of the draw_bmp canvas_dc = wx.MemoryDC(draw_bmp) # fill the canvas white canvas_dc.SetBrush(wx.Brush('white')) canvas_dc.Clear() # draw a bunch of circles ... # pen colour canvas_dc.SetPen(wx.Pen('red', 1)) # fill colour canvas_dc.SetBrush(wx.Brush('yellow')) for x in range(10, 180, 10): y = x r = x canvas_dc.DrawCircle(x, y, r) # now put the canvas drawing into a bitmap to display it # remember the canvas is on top of the draw_bmp self.statbmp.SetBitmap(draw_bmp) def save_image(self): """save the drawing""" finished_image = self.statbmp.GetBitmap() #finished_image.SaveFile("mydrawing.png", wx.BITMAP_TYPE_PNG) finished_image.SaveFile("mydrawing.jpg", wx.BITMAP_TYPE_JPEG) app = wx.App(0) MyFrame(title='draw and save').Show() app.MainLoop()
May 'the Google' be with you!
Just a modification of the above scheme. This time we don't use a blank image, but an image we have and, let's say, write some fancy text on the image and then save it ...
python Syntax (Toggle Plain Text)
# create a canvas on top of an image # then draw some text on the image # and save the finishd drawing import wx class MyFrame(wx.Frame): def __init__(self, parent=None, id=-1, title=None): wx.Frame.__init__(self, parent, id, title) self.statbmp = wx.StaticBitmap(self) self.draw_image() self.save_image() def draw_image(self): # make sure you have the image in the working # directory or give the full path, load the image image = wx.Bitmap("roses.jpg") canvas_dc = wx.MemoryDC(image) # the image is now the background for the canvas canvas_dc.DrawBitmap(image, 0, 0) face = u'Comic Sans MS' font = wx.Font(22, wx.SWISS, wx.NORMAL, wx.NORMAL, False, face) canvas_dc.SetFont(font) canvas_dc.SetTextForeground('red') canvas_dc.DrawText("Sweet Roses!", x=80, y=10) # display the image drawing self.statbmp.SetBitmap(image) def save_image(self): """save the drawing""" finished_image = self.statbmp.GetBitmap() #finished_image.SaveFile("myimage.png", wx.BITMAP_TYPE_PNG) finished_image.SaveFile("myimage.jpg", wx.BITMAP_TYPE_JPEG) app = wx.App(0) MyFrame(title='draw on an image and save it').Show() app.MainLoop()
May 'the Google' be with you!
In case you would ever need to fool with the wx.Frame itself. The wx.Frame default style is wx.DEFAULT_FRAME_STYLE and is normally defined as:
wx.MINIMIZE_BOX|wx.MAXIMIZE_BOX|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.CAPTION|
wx.CLOSE_BOX|wx.CLIP_CHILDREN
so remove wx.MAXIMIZE_BOX to disable it ...
Here is an example of a frame without a border or title bar. Note that you have to supply your own exit button ...
wx.MINIMIZE_BOX|wx.MAXIMIZE_BOX|wx.RESIZE_BORDER|wx.SYSTEM_MENU|wx.CAPTION|
wx.CLOSE_BOX|wx.CLIP_CHILDREN
so remove wx.MAXIMIZE_BOX to disable it ...
python Syntax (Toggle Plain Text)
# a wx.Frame with the max button/box disabled import wx class MyFrame(wx.Frame): def __init__(self, parent, mytitle, mysize): wx.Frame.__init__(self, parent, wx.ID_ANY, mytitle, size=mysize, style=wx.MINIMIZE_BOX|wx.RESIZE_BORDER|wx.SYSTEM_MENU| wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN) app = wx.App(0) # create a MyFrame instance and show the frame MyFrame(None, 'Max box disabled', (400, 300)).Show() app.MainLoop()
python Syntax (Toggle Plain Text)
# wx.Frame with no title bar import wx def exit(event): frame.Close(True) app = wx.App(0) # create a window, no-parent, -1 is default ID, style with no titlebar frame = wx.Frame(parent=None, id=-1, pos=(50,100), size=(300,200), style=wx.MINIMIZE_BOX) frame.SetBackgroundColour('green') # provide exit for a frame without titlebar quit = wx.Button(frame, id=-1, label='Exit', pos=(0,175)) quit.Bind(wx.EVT_BUTTON, exit) # show the window frame.Show(True) # start the event loop app.MainLoop()
May 'the Google' be with you!
Show one of those ever popular animated gif images Zoe style ...
python Syntax (Toggle Plain Text)
# use wx.animate.GIFAnimationCtrl() to show an animated gif import wx import wx.animate # ..\wx\animate.py app = wx.App(0) frame = wx.Frame(None, wx.ID_ANY, "Show an animated gif", size=(250, 150)) frame.SetBackgroundColour("white") # pick an animated GIF file you have in the working directory # (give it the full path if located in another directory) ag_fname = 'AG_Dog.gif' # create the instance with this file name ag = wx.animate.GIFAnimationCtrl(frame, wx.ID_ANY, ag_fname) # clear the background ag.GetPlayer().UseBackgroundColour(True) # continuously loop through the frames of the gif file (default) ag.Play() frame.Show() app.MainLoop()
May 'the Google' be with you!
![]() |
Similar Threads
- Starting Python (Python)
- Autoupdater in wxPython (Python)
- what is python (Python)
Other Threads in the Python Forum
- Previous Thread: sudoku solver problem
- Next Thread: Password Generator
| Thread Tools | Search this Thread |
alarm ansi app assignment avogadro backend beginner binary bluetooth character cipher cmd customdialog cx-freeze data decimals dictionary directory dynamic error exe file float format function generator getvalue gnu graphics halp heads homework http ideas import input ip itunes java keycontrol leftmouse line linux list lists loop maintain maze millimeter module mouse number numbers output parsing path pointer prime programming progressbar push py2exe pygame python queue random recursion schedule screensaverloopinactive script scrolledtext slicenotation sqlite ssh statistics string strings sudokusolver sum text thread threading time tlapse tuple tutorial ubuntu unicode urllib urllib2 variable variables ventrilo vigenere web webservice wikipedia write wxpython xlib






