Author: | Patrick K. O'Brien |
---|---|
Author: | Robin Dunn |
Contact: | pobrien@orbtech.com |
Organization: | Orbtech |
Date: | 2004-02-04 |
Revision: | 1.3 |
In the begining there was Python, and Python had modules, and Python was good. But after a time Guido looked on Python and saw that Python needed organizational assistance, and so Guido took code from Python's side and created Packages and then Python was very good. About this time wxPython was reborn, and wxPython used Packages, but being young and trying to use a new technology wxPython did not know how to use Packages effectivly. wxPython was good, but dreamed of being much better...
Now many years later, after tons of code reorganization and build hacking wxPython has reached that goal. In version 2.4.1 a prototype of this new structure was introduced that dynamically built at import time a new toplevel package named simply "wx" that contained all the items from wxPython.wx but with the names edited to remove the wx prefix. Now in 2.5 the final phase of that switcheroo has been completed and the real classes, functions and constants are now located in the wx package, leaving some compatibility modules in wxPython.wx. This document should answer all the questions you might have concerning the new wx package. Please also take a look at the 2.5 Migration Guide to see notes about other big differences in this release.
This change is being made for a couple of reasons. The first reason is to discourage the use of import *, which is a dangerous technique that can create name conflicts and bloated namespaces.
The second reason is to remove what some perceive to be a "wart." For example, the following code is rather ugly in that the "wx" prefix on the wxFrame class name is no longer useful when you're using the wx module prefix:
from wxPython import wx class Frame(wx.wxFrame)
The new wx package allows you to write code like this, instead:
import wx class Frame(wx.Frame)
The third reason is that the wxWindows project has considered doing the same thing (implement a new wx namespace and drop the "wx" prefix) and we want wxPython to lead the way.
As mentioned in the Introduction, wxPython 2.4.1 introduced a way of getting to this new syntax as quickly as possible. It would import the old names (like "wxFrame") from the old package and then create new names in the wx package without the wx prefix, (like "Frame".) Starting with wxPython 2.5 the renaming is moved up to the wxPython build step, so the real classes and etc. are actually named with the new name (like "Frame") and are located in the new wx package.
For compatibility the old wxPython package still exists, but now it is populated with modules that simply import the new names and then "reverse-renames" them to the old names. It probably sounds a bit complicated, but it is mostly automated and so it doesn't cause problems in most cases.
No. Your existing code will continue to work and be supported for some time. It will be up to you to decide when to switch to the new syntax. But all new documentation and code examples will use the new syntax. So don't wait too long. You wouldn't want anyone calling you old-fashioned, would you?
When you import from wxPython.wx and use a class with the old name, such as wxButton, you are actually using the wx.Button class. I expect that the vast majority of the existing code should work fine using this scheme. The only things that may cause problems is if your old code is depending on some of the implemtation details, or if you are using other things that have changed in the API. See the Migration Guide for more details.
There's more to the old wxPython than just the wxPython.wx module. And we've got those extra modules covered as well. Each of those modules (as well as the lib subpackage) has been moved to the new wx package and reverse-renamers have been placed in the wxPython package as needed.
The wx package is automatically created when you install wxPython version 2.4.1 or higher. So all you have to do is:
import wx
Obviously, you need to change your import statements from:
from wxPython import wx
or:
from wxPython.wx import *
to:
import wx
Then you need to refer to wx attributes without a "wx" prefix, such as:
class MyFrame(wx.Frame):
In most cases, existing code can be modified with a simple search and replace.
The wxPython demo application and most of the sample apps have been converted to use the new import wx style of programming with wxPython, so there are lots of examples to look at and to play with. Here is one of them, it is the simple sample.
#---------------------------------------------------------------------- # A very simple wxPython example. Just a wxFrame, wxPanel, # wxStaticText, wxButton, and a wxBoxSizer, but it shows the basic # structure of any wxPython application. #---------------------------------------------------------------------- import wx class MyFrame(wx.Frame): """ This is MyFrame. It just shows a few controls on a wxPanel, and has a simple menu. """ def __init__(self, parent, title): wx.Frame.__init__(self, parent, -1, title, pos=(150, 150), size=(350, 200)) # Create the menubar menuBar = wx.MenuBar() # and a menu menu = wx.Menu() # add an item to the menu, using \tKeyName automatically # creates an accelerator, the third param is some help text # that will show up in the statusbar menu.Append(wx.ID_EXIT, "E&xit\tAlt-X", "Exit this simple sample") # bind the menu event to an event handler self.Bind(wx.EVT_MENU, self.OnTimeToClose, id=wx.ID_EXIT) # and put the menu on the menubar menuBar.Append(menu, "&File") self.SetMenuBar(menuBar) self.CreateStatusBar() # Now create the Panel to put the other controls on. panel = wx.Panel(self) # and a few controls text = wx.StaticText(panel, -1, "Hello World!") text.SetFont(wx.Font(14, wx.SWISS, wx.NORMAL, wx.BOLD)) text.SetSize(text.GetBestSize()) btn = wx.Button(panel, -1, "Close") funbtn = wx.Button(panel, -1, "Just for fun...") # bind the button events to handlers self.Bind(wx.EVT_BUTTON, self.OnTimeToClose, btn) self.Bind(wx.EVT_BUTTON, self.OnFunButton, funbtn) # Use a sizer to layout the controls, stacked vertically and with # a 10 pixel border around each sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(text, 0, wx.ALL, 10) sizer.Add(btn, 0, wx.ALL, 10) sizer.Add(funbtn, 0, wx.ALL, 10) panel.SetSizer(sizer) panel.Layout() def OnTimeToClose(self, evt): """Event handler for the button click.""" print "See ya later!" self.Close() def OnFunButton(self, evt): """Event handler for the button click.""" print "Having fun yet?" class MyApp(wx.App): def OnInit(self): frame = MyFrame(None, "Simple wxPython App") frame.Show(True) self.SetTopWindow(frame) return True app = MyApp(True) app.MainLoop()