2003-11-12 21:34:20 +00:00
|
|
|
============================
|
|
|
|
wxPython 2.5 Migration Guide
|
|
|
|
============================
|
|
|
|
|
|
|
|
This document will help explain some of the major changes in wxPython
|
|
|
|
2.5 and let you know what you need to do to adapt your programs to
|
|
|
|
those changes. Be sure to also check in the CHANGES.txt file like
|
|
|
|
usual to see info about the not so major changes and other things that
|
|
|
|
have been added to wxPython.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Module Initialization
|
|
|
|
---------------------
|
|
|
|
|
|
|
|
The import-startup-bootstrap process employed by wxPython was changed
|
|
|
|
such that wxWindows and the underlying gui toolkit are **not**
|
|
|
|
initialized until the wx.App object is created (but before wx.App.OnInit
|
|
|
|
is called.) This was required because of some changes that were made
|
|
|
|
to the C++ wxApp class.
|
|
|
|
|
|
|
|
There are both benefits and potential problems with this change. The
|
|
|
|
benefits are that you can import wxPython without requiring access to
|
|
|
|
a GUI (for checking version numbers, etc.) and that in a
|
|
|
|
multi-threaded environment the thread that creates the app object will
|
|
|
|
now be the GUI thread instead of the one that imports wxPython. Some
|
|
|
|
potential problems are that the C++ side of the "stock-objects"
|
|
|
|
(wx.BLUE_PEN, wx.TheColourDatabase, etc.) are not initialized until
|
|
|
|
the wx.App object is created, so you should not use them until after
|
|
|
|
you have created your wx.App object. (In fact, until I find a better
|
|
|
|
solution trying to use one of the stock objects before the app is
|
|
|
|
created will probably result in a crash.)
|
|
|
|
|
|
|
|
Also, you will probably not be able to do any kind of GUI or bitmap
|
|
|
|
operation unless you first have created an app object, (even on
|
|
|
|
Windows where most anything was possible before.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SWIG 1.3
|
|
|
|
--------
|
|
|
|
|
|
|
|
wxPython is now using SWIG 1.3.x from CVS (with several of my own
|
|
|
|
customizations added that I hope to get folded back into the main SWIG
|
|
|
|
distribution.) This has some far reaching ramifications:
|
|
|
|
|
|
|
|
All classes derive from object and so all are now "new-style
|
|
|
|
classes"
|
|
|
|
|
|
|
|
Public data members of the C++ classes are wrapped as Python
|
|
|
|
properties using property() instead of using __getattr__/__setattr__
|
|
|
|
like before. Normally you shouldn't notice any difference, but if
|
|
|
|
you were previously doing something with __getattr__/__setattr__
|
|
|
|
in derived classes then you may have to adjust things.
|
|
|
|
|
|
|
|
Static C++ methods are wrapped using the staticmethod()
|
|
|
|
feature of Python and so are accessible as ClassName.MethodName
|
|
|
|
as expected. They are still available as top level functions
|
|
|
|
ClassName_MethodName as before.
|
|
|
|
|
|
|
|
The relationship between the wxFoo and wxFooPtr classes have
|
|
|
|
changed for the better. Specifically, all instances that you see
|
|
|
|
will be wxFoo even if they are created internally using wxFooPtr,
|
|
|
|
because wxFooPtr.__init__ will change the instance's __class__ as
|
|
|
|
part of the initialization. If you have any code that checks
|
|
|
|
class type using something like isinstance(obj, wxFooPtr) you will
|
|
|
|
need to change it to isinstance(obj, wxFoo).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Binding Events
|
|
|
|
--------------
|
|
|
|
|
|
|
|
All of the EVT_* functions are now instances of the wx.PyEventBinder
|
|
|
|
class. They have a __call__ method so they can still be used as
|
|
|
|
functions like before, but making them instances adds some
|
|
|
|
flexibility.
|
|
|
|
|
|
|
|
wx.EvtHandler (the base class for wx.Window) now has a Bind method that
|
|
|
|
makes binding events to windows a little easier. Here is its
|
|
|
|
definition and docstring::
|
|
|
|
|
|
|
|
def Bind(self, event, handler, source=None, id=wxID_ANY, id2=wxID_ANY):
|
|
|
|
"""
|
|
|
|
Bind an event to an event handler.
|
|
|
|
|
|
|
|
event One of the EVT_* objects that specifies the
|
|
|
|
type of event to bind.
|
|
|
|
|
|
|
|
handler A callable object to be invoked when the event
|
|
|
|
is delivered to self. Pass None to disconnect an
|
|
|
|
event handler.
|
|
|
|
|
|
|
|
source Sometimes the event originates from a different window
|
|
|
|
than self, but you still want to catch it in self. (For
|
|
|
|
example, a button event delivered to a frame.) By
|
|
|
|
passing the source of the event, the event handling
|
|
|
|
system is able to differentiate between the same event
|
|
|
|
type from different controls.
|
|
|
|
|
|
|
|
id,id2 Used for menu IDs or for event types that require a
|
|
|
|
range of IDs
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
Some examples of its use::
|
|
|
|
|
|
|
|
self.Bind(wx.EVT_SIZE, self.OnSize)
|
|
|
|
self.Bind(wx.EVT_BUTTON, self.OnButtonClick, theButton)
|
|
|
|
self.Bind(wx.EVT_MENU, self.OnExit, id=ID_EXIT)
|
|
|
|
|
|
|
|
I hope to be able to remove the need for using IDs even for menu
|
|
|
|
events too...
|
|
|
|
|
|
|
|
If you create your own custom event types and EVT_* functions, and you
|
|
|
|
want to be able to use them with the Bind method above then you should
|
|
|
|
change your EVT_* to be an instance of wxPyEventBinder instead of a
|
|
|
|
function. If you used to have something like this::
|
|
|
|
|
|
|
|
myCustomEventType = wxNewEventType()
|
|
|
|
def EVT_MY_CUSTOM_EVENT(win, id, func):
|
|
|
|
win.Connect(id, -1, myCustomEventType, func)
|
|
|
|
|
|
|
|
|
|
|
|
Change it like so::
|
|
|
|
|
|
|
|
myCustomEventType = wxNewEventType()
|
|
|
|
EVT_MY_CUSTOM_EVENT = wxPyEventBinder(myCustomEventType, 1)
|
|
|
|
|
|
|
|
The second parameter is an integer in [0, 1, 2] that specifies the
|
|
|
|
number of IDs that are needed to be passed to Connect.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The wx Namespace
|
|
|
|
----------------
|
|
|
|
|
|
|
|
The second phase of the wx Namespace Transition has begun. That means
|
|
|
|
that the real names of the classes and other symbols do not have the
|
|
|
|
'wx' prefix and the modules are located in a Python package named
|
|
|
|
wx. There is still a Python package named wxPython with modules
|
|
|
|
that have the names with the wx prefix for backwards compatibility.
|
|
|
|
Instead of dynamically changing the names at module load time like in
|
|
|
|
2.4, the compatibility modules are generated at build time and contain
|
|
|
|
assignment statements like this::
|
|
|
|
|
|
|
|
wxWindow = wx.core.Window
|
|
|
|
|
|
|
|
Don't let the "core" in the name bother you. That and some other
|
|
|
|
modules are implementation details, and everything that was in the
|
|
|
|
wxPython.wx module before will still be in the wx package namespace
|
|
|
|
after this change. So from your code you would use it as wx.Window.
|
|
|
|
|
|
|
|
A few notes about how all of this was accomplished might be
|
|
|
|
interesting... SWIG is now run twice for each module that it is
|
|
|
|
generating code for. The first time it outputs an XML representaion
|
|
|
|
of the parse tree, which can be up to 20MB and 300K lines in size!
|
|
|
|
That XML is then run through a little Python script that creates a
|
|
|
|
file full of SWIG %rename directives that take the wx off of the
|
|
|
|
names, and also generates the Python compatibility file described
|
|
|
|
above that puts the wx back on the names. SWIG is then run a second
|
|
|
|
time to generate the C++ code to implement the extension module, and
|
|
|
|
uses the %rename directives that were generated in the first step.
|
|
|
|
|
|
|
|
Not every name is handled correctly (but the bulk of them are) and so
|
|
|
|
some work has to be done by hand, especially for the reverse-renamers.
|
|
|
|
So expect a few flaws here and there until everything gets sorted out.
|
|
|
|
|
|
|
|
In summary, the wx package and names without the "wx" prefix are now
|
|
|
|
the official form of the wxPython classes. For example::
|
|
|
|
|
|
|
|
import wx
|
|
|
|
|
|
|
|
class MyFrame(wx.Frame):
|
|
|
|
def __init__(self, parent, title):
|
|
|
|
wx.Frame.__init__(self, parent, -1, title)
|
|
|
|
p = wx.Panel(self, -1)
|
|
|
|
b = wx.Button(p, -1, "Do It", (10,10))
|
|
|
|
self.Bind(wx.EVT_BUTTON, self.JustDoIt, b)
|
|
|
|
|
|
|
|
def JustDoIt(self, evt):
|
|
|
|
print "It's done!"
|
|
|
|
|
|
|
|
app = wx.PySimpleApp()
|
|
|
|
f = MyFrame(None, "What's up?")
|
|
|
|
f.Show()
|
|
|
|
app.MainLoop()
|
|
|
|
|
|
|
|
You shouldn't need to migrate all your modules over to use the new
|
|
|
|
package and names right away as there are modules in place that try to
|
|
|
|
provide as much backwards compatibility of the names as possible. If
|
|
|
|
you rewrote the above sample using "from wxPython.wx import *", the
|
|
|
|
old wxNames, and the old style of event binding it will still work
|
|
|
|
just fine.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
New wx.DC Methods
|
|
|
|
-----------------
|
|
|
|
|
|
|
|
Many of the Draw methods of wx.DC have alternate forms in C++ that take
|
|
|
|
wxPoint or wxSize parameters (let's call these *Type A*) instead of
|
|
|
|
the individual x, y, width, height, etc. parameters (and we'll call
|
|
|
|
these *Type B*). In the rest of the library I normally made the *Type
|
|
|
|
A* forms of the methods be the default method with the "normal" name,
|
|
|
|
and had renamed the *Type B* forms of the methods to some similar
|
|
|
|
name. For example in wx.Window we have these Python methods::
|
|
|
|
|
|
|
|
SetSize(size) # Type A
|
|
|
|
SetSizeWH(width, height) # Type B
|
|
|
|
|
|
|
|
|
|
|
|
For various reasons the new *Type A* methods in wx.DC were never added
|
|
|
|
and the existing *Type B* methods were never renamed. Now that lots
|
|
|
|
of other things are also changing in wxPython it has been decided that
|
|
|
|
it is a good time to also do the method renaming in wx.DC too in order
|
|
|
|
to be consistent with the rest of the library. The methods in wx.DC
|
|
|
|
that are affected are listed here::
|
|
|
|
|
|
|
|
FloodFillXY(x, y, colour, style = wx.FLOOD_SURFACE)
|
|
|
|
FloodFill(point, colour, style = wx.FLOOD_SURFACE)
|
|
|
|
|
|
|
|
GetPixelXY(x, y)
|
|
|
|
GetPixel(point)
|
|
|
|
|
|
|
|
DrawLineXY(x1, y1, x2, y2)
|
|
|
|
DrawLine(point1, point2)
|
|
|
|
|
|
|
|
CrossHairXY(x, y)
|
|
|
|
CrossHair(point)
|
|
|
|
|
|
|
|
DrawArcXY(x1, y1, x2, y2, xc, yc)
|
|
|
|
DrawArc(point1, point2, center)
|
|
|
|
|
|
|
|
DrawCheckMarkXY(x, y, width, height)
|
|
|
|
DrawCheckMark(rect)
|
|
|
|
|
|
|
|
DrawEllipticArcXY(x, y, w, h, start_angle, end_angle)
|
|
|
|
DrawEllipticArc(point, size, start_angle, end_angle)
|
|
|
|
|
|
|
|
DrawPointXY(x, y)
|
|
|
|
DrawPoint(point)
|
|
|
|
|
|
|
|
DrawRectangleXY(x, y, width, height)
|
|
|
|
DrawRectangle(point, size)
|
|
|
|
DrawRectangleRect(rect)
|
|
|
|
|
|
|
|
DrawRoundedRectangleXY(x, y, width, height, radius)
|
|
|
|
DrawRoundedRectangle(point, size, radius)
|
|
|
|
DrawRoundedRectangleRect(rect, radius)
|
|
|
|
|
|
|
|
DrawCircleXY(x, y, radius)
|
|
|
|
DrawCircle(point, radius)
|
|
|
|
|
|
|
|
DrawEllipseXY(x, y, width, height)
|
|
|
|
DrawEllipse(point, size)
|
|
|
|
DrawEllipseRect(rect)
|
|
|
|
|
|
|
|
DrawIconXY(icon, x, y)
|
|
|
|
DrawIcon(icon, point)
|
|
|
|
|
|
|
|
DrawBitmapXY(bmp, x, y, useMask = FALSE)
|
|
|
|
DrawBitmap(bmp, point, useMask = FALSE)
|
|
|
|
|
|
|
|
DrawTextXY(text, x, y)
|
|
|
|
DrawText(text, point)
|
|
|
|
|
|
|
|
DrawRotatedTextXY(text, x, y, angle)
|
|
|
|
DrawRotatedText(text, point, angle)
|
|
|
|
|
|
|
|
|
|
|
|
BlitXY(xdest, ydest, width, height, sourceDC, xsrc, ysrc,
|
|
|
|
rop = wxCOPY, useMask = FALSE, xsrcMask = -1, ysrcMask = -1)
|
|
|
|
Blit(destPt, size, sourceDC, srcPt,
|
|
|
|
rop = wxCOPY, useMask = FALSE, srcPtMask = wx.DefaultPosition)
|
|
|
|
|
2003-11-28 18:42:44 +00:00
|
|
|
SetClippingRegionXY SetClippingRegion(x, y, width, height)
|
|
|
|
SetClippingRegion(point, size)
|
|
|
|
SetClippingRect(rect)
|
|
|
|
SetClippingRegionAsRegion(region);
|
|
|
|
|
2003-11-12 21:34:20 +00:00
|
|
|
|
|
|
|
If you have code that draws on a DC you **will** get errors because of
|
|
|
|
these changes, but it should be easy to fix the code. You can either
|
|
|
|
change the name of the *Type B* method called to the names shown
|
|
|
|
above, or just add parentheses around the parameters as needed to turn
|
|
|
|
them into tuples and let the SWIG typemaps turn them into the wx.Point
|
|
|
|
or wx.Size object that is expected. Then you will be calling the new
|
|
|
|
*Type A* method. For example, if you had this code before::
|
|
|
|
|
|
|
|
dc.DrawRectangle(x, y, width, height)
|
|
|
|
|
|
|
|
You could either continue to use the *Type B* method bu changing the
|
|
|
|
name to DrawRectabgleXY, or just change it to the new *Type A* by
|
|
|
|
adding some parentheses like this::
|
|
|
|
|
|
|
|
dc.DrawRectangle((x, y), (width, height))
|
|
|
|
|
|
|
|
Or if you were already using a point and size::
|
|
|
|
|
|
|
|
dc.DrawRectangle(p.x, p.y, s.width, s.height)
|
|
|
|
|
|
|
|
Then you can just simplify it like this::
|
|
|
|
|
|
|
|
dc.DrawRectangle(p, s)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Building, Extending and Embedding wxPython
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
wxPython's setup.py script now expects to use existing libraries for
|
|
|
|
the contribs (gizmos, stc, xrc, etc.) rather than building local
|
|
|
|
copies of them. If you build your own copies of wxPython please be
|
|
|
|
aware that you now need to also build the ogl, stc, xrc, and gizmos
|
|
|
|
libraries in addition to the main wx lib. [[TODO: update the
|
|
|
|
BUILD.*.txt files too!]]
|
|
|
|
|
|
|
|
The wxPython.h and other header files are now in
|
|
|
|
.../wxPython/include/wx/wxPython instead of in wxPython/src. You should
|
|
|
|
include it via the "wx/wxPython/wxPython.h" path and add
|
|
|
|
.../wxPython/include to your list of include paths. [[TODO: Install
|
|
|
|
these headers on Linux...]]
|
|
|
|
|
|
|
|
You no longer need to call wxClassInfo::CleanUpClasses() and
|
|
|
|
wxClassInfo::InitializeClasses() in your extensions or when embedding
|
|
|
|
wxPython.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Two (or Three!) Phase Create
|
|
|
|
----------------------------
|
|
|
|
|
|
|
|
If you use the Precreate/Create method of instantiating a window, (for
|
|
|
|
example, to set an extended style flag, or for XRC handlers) then
|
|
|
|
there is now a new method named PostCreate to help with transplanting
|
|
|
|
the brain of the prewindow instance into the derived window instance.
|
|
|
|
For example::
|
|
|
|
|
|
|
|
class MyDialog(wx.Dialog):
|
|
|
|
def __init__(self, parent, ID, title, pos, size, style):
|
|
|
|
pre = wx.PreDialog()
|
|
|
|
pre.SetExtraStyle(wx.DIALOG_EX_CONTEXTHELP)
|
|
|
|
pre.Create(parent, ID, title, pos, size, style)
|
|
|
|
self.PostCreate(pre)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sizers
|
|
|
|
------
|
|
|
|
|
|
|
|
The hack allowing the old "option" keyword parameter has been
|
|
|
|
removed. If you use keyworkd args with wxSizer Add, Insert, or
|
|
|
|
Prepend then you will need to use the "proportion" name instead of
|
|
|
|
"option".
|
|
|
|
|
|
|
|
When adding a spacer to a sizer you now need to use a wxSize or a
|
|
|
|
2-integer sequence instead of separate width and height parameters.
|
|
|
|
|
|
|
|
The wxGridBagSizer class (very similar to the RowColSizer in the
|
|
|
|
library) has been added to C++ and wrapped for wxPython. It can also
|
|
|
|
be used from XRC.
|
|
|
|
|
|
|
|
You should not use AddWindow, AddSizer, AddSpacer (and similar for
|
|
|
|
Insert, Prepend, and etc.) methods any longer. Just use Add and the
|
|
|
|
wrappers will figure out what to do.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Other Stuff
|
|
|
|
-----------
|
|
|
|
|
|
|
|
Instead of over a dozen separate extension modules linked together
|
|
|
|
into a single extension module, the "core" module is now just a few
|
|
|
|
extensions that are linked independently, and then merged together
|
|
|
|
later into the main namespace via Python code.
|
|
|
|
|
|
|
|
Because of the above, the "internal" module names have changed, but
|
|
|
|
you shouldn't have been using them anyway so it shouldn't bother
|
|
|
|
you. ;-)
|
|
|
|
|
|
|
|
The wxPython.help module no longer exists and the classes therein are
|
|
|
|
now part of the core module imported with wxPython.wx or the wx
|
|
|
|
package.
|
|
|
|
|
|
|
|
wxPyDefaultPosition and wxPyDefaultSize are gone. Use the
|
|
|
|
wxDefaultPosition and wxDefaultSize objects instead.
|
|
|
|
|
|
|
|
Similarly, the wxSystemSettings backwards compatibiility aliases for
|
|
|
|
GetSystemColour, GetSystemFont and GetSystemMetric have also gone into
|
|
|
|
the bit-bucket. Use GetColour, GetFont and GetMetric instead.
|
|
|
|
|
|
|
|
|
2003-12-03 01:38:53 +00:00
|
|
|
The wx.NO_FULL_REPAINT_ON_RESIZE style is now the default style for
|
|
|
|
all windows. The name still exists for compatibility, but it is set
|
|
|
|
to zero. If you want to disable the setting (so it matches the old
|
|
|
|
default) then you need to use the new wx.FULL_REPAINT_ON_RESIZE style
|
|
|
|
flag otherwise only the freshly exposed areas of the window will be
|
|
|
|
refreshed.
|
2003-11-12 21:34:20 +00:00
|
|
|
|
2003-12-04 01:15:11 +00:00
|
|
|
wxPyTypeCast has been removed. Since we've had the OOR (Original
|
|
|
|
Object Return) for a couple years now there should be no need to use
|
|
|
|
wxPyTypeCast at all.
|
2003-11-12 21:34:20 +00:00
|
|
|
|