Name:
[002] Ian Ozsvald
Member:
90 months
Authored:
181 videos
Description:
I am the co-founder of ShowMeDo (see http://showmedo.com/about), author of `The Screencasting Handbook <http://thescreencastinghandbook.com>`_ and the founder of the professional screencast production company `ProCasts <http://procasts.co.uk>`_:
.. image:: http://procasts.co.uk/media/procasts_sma ...
Worked Solution - adding a Mirror function to the Image Viewer [ID:550] (10/14)
in series: Build a wxPython Image Viewer
video tutorial by Ian Ozsvald, added 03/08
Name:
[002] Ian Ozsvald
Member:
90 months
Authored:
181 videos
Description:
I am the co-founder of ShowMeDo (see http://showmedo.com/about), author of `The Screencasting Handbook <http://thescreencastinghandbook.com>`_ and the founder of the professional screencast production ...
Our authors tell us that feedback from you is a big motivator. Please take a few moments to let them know what you think of their work.
First of all we uncomment the Mirror menu code and run the application without defining the OnMirrorImage function - we get an AttributeError exception on the Frame.
Next we create an empty OnMirrorImage function and Enable the menu item in OnOpen after the wx.ID_OK.
Next we use the image's Mirror() function, our ShowBitmap() and the Frame's Refresh() to correctly flip the image.
import os
import wx
MAIN_WINDOW_DEFAULT_SIZE = (300,200)
class Frame(wx.Frame):
def __init__(self, parent, id, title):
style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER) # XOR to remove the resizeable border
wx.Frame.__init__(self, parent, id, title=title, size=MAIN_WINDOW_DEFAULT_SIZE, style=style)
self.Center() # open in the centre of the screen
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour('White') # make the background of the window white
self.CreateMenuBar()
# create a StatusBar and give it 2 columns
self.statusBar = self.CreateStatusBar()
self.statusBar.SetFieldsCount(2)
self.statusBar.SetStatusText('No image specified', 1)
self.bitmap = None # set to None as we refer to it in ShowBitmap before we instantiate it
def CreateMenuBar(self):
"Create a menu bar with Open, Exit items"
menuBar = wx.MenuBar()
# Tell our Frame about this MenuBar
self.SetMenuBar(menuBar)
menuFile = wx.Menu()
menuBar.Append(menuFile, '&File')
# NOTE on wx ids - they're used everywhere, we don't care about them
# Used to handle events and other things
# An id can be -1 or wx.ID_ANY, wx.NewId(), your own id
# Get the id using object.GetId()
fileOpenMenuItem = menuFile.Append(-1, '&Open Image', 'Open a picture')
#print "fileOpenMenuItem.GetId()", fileOpenMenuItem.GetId()
self.Bind(wx.EVT_MENU, self.OnOpen, fileOpenMenuItem)
# add a 'mirror' option, disable it for now
# we add mirrorMenuItem to self so that we can reference it later
self.mirrorMenuItem = menuFile.Append(-1, '&Mirror Image', 'Mirror the image horizontally')
self.mirrorMenuItem.Enable(False) # we can't mirror an image until we've loaded one in, so start with 'mirror' disabled
self.Bind(wx.EVT_MENU, self.OnMirrorImage, self.mirrorMenuItem)
# create a menu item for Exit and bind it to the OnExit function
exitMenuItem = menuFile.Append(-1, 'E&xit', 'Exit the viewer')
self.Bind(wx.EVT_MENU, self.OnExit, exitMenuItem)
# add a Help menu with an About item
#menuHelp = wx.Menu()
#menuBar.Append(menuHelp, '&Help')
#helpMenuItem = menuHelp.Append(-1, '&About', 'About screen')
#self.Bind(wx.EVT_MENU, self.OnAbout, helpMenuItem)
def OnMirrorImage(self, event):
# ask the Image to mirror itself on the x-axis
self.image = self.image.Mirror()
# whilst we mirror it and show it, we haven't yet forced a repaint so we won't see it unless we hide the window
self.ShowBitmap()
# now we can ask for a refresh which repaints the image
self.Refresh()
def OnOpen(self, event):
"Open an image file, set title if successful"
# Create a file-open dialog in the current directory
filters = 'Image files (*.gif;*.png;*.jpg)|*.gif;*.png;*.jpg'
dlg = wx.FileDialog(self, message="Open an Image...", defaultDir=os.getcwd(),
defaultFile="", wildcard=filters, style=wx.OPEN)
# Call the dialog as a model-dialog so we're required to choose Ok or Cancel
if dlg.ShowModal() == wx.ID_OK:
# User has selected something, get the path, set the window's title to the path
filename = dlg.GetPath()
self.SetTitle(filename)
wx.BeginBusyCursor()
# load the image from the filename
self.image = wx.Image(filename, wx.BITMAP_TYPE_ANY, -1) # auto-detect file type
# set the StatusBar to show the image's size
self.statusBar.SetStatusText('Size = %s' % (str(self.image.GetSize())) , 1)
# display the image inside the panel
self.ShowBitmap()
# enable the 'Mirror' menu item, it only makes sense to enable it when we've loaded
# an image as before there would be no image to mirror
self.mirrorMenuItem.Enable(True)
wx.EndBusyCursor()
dlg.Destroy() # we don't need the dialog any more so we ask it to clean-up
def ShowBitmap(self):
if self.bitmap is not None:
self.bitmap.Destroy()
# Convert to Bitmap for wxPython to draw it to screen
self.bitmap = wx.StaticBitmap(self.panel, -1, wx.BitmapFromImage(self.image))
# Make the application's window as large as the image
self.SetClientSize(self.bitmap.GetSize())
self.Center() # open in the centre of the screen
def OnExit(self, event):
"Close the application by Destroying the object"
self.Destroy()
class App(wx.App):
def OnInit(self):
self.frame = Frame(parent=None, id=-1, title='Image Viewer')
self.frame.Show()
self.SetTopWindow(self.frame)
return True
if __name__ == "__main__":
# make an App object, set stdout to the console so we can see errors
app = App(redirect=False)
app.MainLoop()
Got any questions?
Get answers in the ShowMeDo Learners Google Group.
Video statistics:
- Video's rank shown in the most popular listing
- Video plays: 76 (since July 30th)
- Plays in last week: 0
- Published: 63 months ago
Thank-yous, questions and comments
If this video tutorial was helpful please take some time to say thank-you to the authors for their hard work. Feel free to ask questions. Let the author know why their video tutorial was useful - what are you learning about? Did the video tutorial save you time? Would you like to see more?
You may also want to see our ShowMeDo Google Group to speak to our active users and authors.
All comments excluding tick-boxed quick-comments
Just right.
Thanks,
Mark
You certainly got my attention with the "big exercise". I found it rather amusing.
I thought the exercise was fine/solvable and the links to the wxPython documentation was clue enough. I've liked the videos so far.
I do think it's a shame that the previous versions of the code contains the commented "Mirror image" menu item. It would add to the exercise if the user should copy/paste the "Open Image" item and so on...
On Debian Linux (Python 2.5.4/ wx 2.6.3) refreshing the mirrored image isn't a problem.
The instructions were clear enough for me to do this without help.
However, I did not need to use self.Refresh().
However #2, I wonder why you have put self.Refresh() into OnMirrorImage() and not ShowBitmap(), as it's obviously ShowBitmap() that is functioning incorrectly?
I am enjoying the series but as a newbie I found the exercise too challenging at first so I had to watch the beginning of this video to be able to solve it. I got confused with 'self' and kept getting errors saying the frame not being able to mirror. As soon as I saw "self.image = self.image.Mirror()" on this video I was able to stop and solve the exercise.
I did have some successes with this which are worth mentioning. I did figure out how to set up the OnMirrorImage function straight away; but couldn't find the right lines of code to make the image actually mirror until after watching this episode. I also figured out how to mirror the image vertically; using boolean logic if Mirror( horizontal=True), then Mirror(False) will mirror the image vertically :-)
As in: ( self.image = self.image.Mirror(False) )
Review of Worked Solution - adding a Mirror function to the Image Viewer
This was a good exercise and I had fun doing
it.
I did attempt to solve the problem myself; however, I couldn't find the documentation for the solution on the wxpython.org/ wxwidgets.org websites or any other site. I do not know if I was looking in the wrong place or there is a lack of this kind of documentation.
In fact, looking at the documentation at wxpython.org is totally confusing.
Which did not suprise me, as most free documentation on websites is typically much more difficult to interpret than a textbook.
I did find the book "WxPython in Action" on the wxpython.org website. That looks to be a very good reference manual, I'll have to get that one.
Perhaps that would make a good ShowMeDo video; on how to use the wxpython.org documentation to solve these types of problems or whether there is a better source elsewhere on the net?
On a side note; I find sample code to be a good reference when solving problems such as this.WxPython comes with a great deal of different sample source projects, which helps.
So I did have to cheat and watch the next video for the answer. Searching the web, trying to find documentation to get your code to work reminds me of how much time ShowMeDo saves me :-)
I'm running under Ubuntu 8.04, Gnome. When I comment out:
#self.Refresh()
I don't see any redraw problem. When I mirror the picture looks the same. This might be a linux thing. Great video. Keep it up!
Video published, thanks for contributing to ShowMeDo
