== Style Guide for wxPython code ==

This is a little style guide for using wxPython. It's not the be-all and
end-all of how wxPython code should be written, but what I've tried to
capture is a way to write wxPython code that is clear and Pythonic. It
was vetted on the wxPython-users mailing list, with very little
disagreement.

Pythonic is partly defined by:

http://www.python.org/doc/humor/#the-zen-of-python

This is about how to use wxPython-specific classes and structure. For code formatting advice, particularly if you want to include it in the wxPython lib, see: http://wxpython.org/codeguidelines.php

1. Use `import wx` NEVER use `from wx import *` or the ancient `from wxPython.wx import *`.
   Don't use `import *` for other libs either.
   <<BR>>
   <<BR>>
   BECAUSE: Namespaces are one honking great idea.
   <<BR>>
   <<BR>>
   For modules that are buried deep in a package, you can use:

   `from wx.lib.SomeLib import SomeModule`
   <<BR>>
   As no one wants to type:

   `AnObject = wx.lib.SomeLib.SomeModule.SomeClass()`


2. Keyword arguments in constructors.

   If you find yourself putting in a bunch of unneeded defaults
   like `wx.DefaultSize, wx.DefaultPosition, wx.ID_ANY`, etc. in
   constructors, use keyword arguments:

   `MainFrame = wx.Frame(None, title="A Title", size=(500, 400))`
   <<BR>>
   <<BR>>
   BECAUSE: Explicit is better than implicit.

2b. Use `*args` and `**kwargs` when subclassing `wx.Windows`:

{{{
class MyPanel(wx.Panel):
    """This Panel does some custom thing"""
    def __init__(self, *args, **kwargs):
        """Create the DemoPanel."""
        wx.Panel.__init__(self, *args, **kwargs)
}}}

   This allows your custom Window to take all the same arguments as a standard Window, without your having to anticipate which ones might be useful in advance.


3. Don't use IDs. There is very rarely a good reason to use them.

   BECAUSE: Simple is better than complex.

   * Most Widget constructors will fill in a default ID for you, so you
   don't have to specify one at all. Other arguments can be specified as
   key word arguments (see above):

   `MyFrame = wx.Frame(None, title="A Title", size=(400,400))`

   `AButton = wx.Button(self, label="Push Me")`

   * If the id is a required argument, use `wx.ID_ANY`. Because `wx.ID_ANY == -1`,
   you may see -1 used for an id in code, but use wx.ID_ANY to make your code
   clearer. And who knows, maybe that magic value will change one day.

   wx.ID_ANY is more explicit, as it is self-documenting and descriptive.
   Using the numeric value of named constants in general is extremely
   poor practice in any programming language. (Chris Mellon)
   <<BR>>
   <<BR>>
   BECAUSE: Explicit is better than implicit.
   <<BR>>
   <<BR>>
   EXCEPTION: (there's always an exception!)  Use standard IDs for
   standard menus, buttons, etc. It is useful to use the standard IDs
   because they may turn on standard functionality, such as menu item
   remapping for wxMac, automatic Dialog completion or cancellation,
   using stock button labels and images, etc. A list of these standard
   IDs can be found in the "Constants -- Stock items" section of the wxWidgets
   Reference manual. Example:
   <<BR>>
   `item = FileMenu.Append(wx.ID_EXIT, "&Quit")`

   NOTE: On OSX Cocoa both the about and the quit menu belong to the bold 'app menu', and that's why you don't find them anymore in the file menu.
         using the standard Ids allows wx to place these items in their correct location. By using your own ids you just block this ability to play by       the rules.


4. Use the `Bind()` method to bind events:

   * A pushbutton example:

   `AButton = wx.Button(self, label="Push Me")`

   `AButton.Bind(wx.EVT_BUTTON, self.OnButtonPush)`

   * You can use `Bind()` for menus too, even though they don't have a
   `Bind()` method, in this way:

   `FileMenu = wx.Menu()`

   `item = FileMenu.Append(wx.ID_EXIT, "&Quit")`

   `self.Bind(wx.EVT_MENU, self.OnQuit, item)`

   (where `self` is a `wx.Frame`)

5. Use Sizers!

   If you use Sizers rather than absolute positioning, you get code
   that:

   * Works better across platforms: different platforms have different
   size widgets.

   * Easily adapts to different languages: different languages have
   different length labels, etc.

   * Works better even on one platform is the user uses a different
   default font, different theme.

   * Is more maintainable: If you need to change, remove or add a
   widget, the rest of your dialog or panel can re-arrange itself.

6. `wx.App()` now has the same built in functionality as `wx.PySimpleApp()`,
   so there is no need for the latter.

   Note: The above is not true on MacOS X. When using `wx.App`, tracebacks are
   shown in a dialog which instantly disappears as your app dies (unless
   run with pythonw -i). With `wx.PySimpleApp`, tracebacks go to stdout.

7. Use separate, custom classes rather than nesting lots of `wx.Panels` in one class.
   If you find yourself doing this in an `__init__:`

   `self.MainPanel = wx.Panel(self, ...`

   `self.SubPanel1 = wx.Panel(self.MainPanel, ..)`

   `self.SubPanel2 = wx.Panel(self.SubPanel1, ...)`

   `MyButton = wx.Button(self.SubPanel2, ....)`
   <<BR>>
   <<BR>>
   Then you are creating an ugly, hard to maintain, mess!
   <<BR>>
   Instead, create custom classes for the stuff that all is working together in a panel:

   `class MainPanel(wx.Panel):`
       ....

   `class SubPanel1(wx.Panel):`
       ....

   etc.

   You'll also find that by doing this, you're less likely to break the
   "Don't Repeat Yourself" (DRY) principle. Often you'll find that you
   have group of widgets that are common to various parts of your
   app. If you put them on a custom panel, you'll be able to re-use that
   code. Try to make each of these widgets autonomous, so they can be
   plugged in elsewhere in your app, or even another application.

   If your widget has to communicate with other controls define your own
   custom events and use them to communicate with other controls. Almost
   as a unit test it is nice to write a little demo app, which only uses
   that widget and demonstrates all its functionality.

8. Use native Python stuff rather than wx stuff where possible:

   BECAUSE: Simple is better than complex.

   For example, use  `size=(500, 400)` rather than `size=wx.Size(500, 400)`

9. Use docstrings, consistently.


10. Use the StdDialogButtonSizer with buttons using standard wx.IDs when subclassing dialogs to place the buttons correctly for the user's platform.

{{{
#!python
    okButton = wx.Button(self, wx.ID_OK, "&OK")
    okButton.SetDefault()
    cancelButton = wx.Button(self, wx.ID_CANCEL, "&Cancel")
    btnSizer = wx.StdDialogButtonSizer()
    btnSizer.AddButton(okButton)
    btnSizer.AddButton(cancelButton)
    btnSizer.Realize()
}}}



=== Example ===
{{{
#!python
#!/usr/bin/env python2.4

# I like to put the python version on the #! line,
# so that I can have multiple versions installed.

"""

This is a small wxPython app developed to demonstrate how to write
Pythonic wxPython code.

"""

import wx

class DemoPanel(wx.Panel):
    """This Panel hold two simple buttons, but doesn't really do anything."""
    def __init__(self, parent, *args, **kwargs):
        """Create the DemoPanel."""
        wx.Panel.__init__(self, parent, *args, **kwargs)

        self.parent = parent  # Sometimes one can use inline Comments

        NothingBtn = wx.Button(self, label="Do Nothing with a long label")
        NothingBtn.Bind(wx.EVT_BUTTON, self.DoNothing )

        MsgBtn = wx.Button(self, label="Send Message")
        MsgBtn.Bind(wx.EVT_BUTTON, self.OnMsgBtn )

        Sizer = wx.BoxSizer(wx.VERTICAL)
        Sizer.Add(NothingBtn, 0, wx.ALIGN_CENTER|wx.ALL, 5)
        Sizer.Add(MsgBtn, 0, wx.ALIGN_CENTER|wx.ALL, 5)

        self.SetSizerAndFit(Sizer)

    def DoNothing(self, event=None):
        """Do nothing."""
        pass

    def OnMsgBtn(self, event=None):
        """Bring up a wx.MessageDialog with a useless message."""
        dlg = wx.MessageDialog(self,
                               message='A completely useless message',
                               caption='A Message Box',
                               style=wx.OK|wx.ICON_INFORMATION
                               )
        dlg.ShowModal()
        dlg.Destroy()

class DemoFrame(wx.Frame):
    """Main Frame holding the Panel."""
    def __init__(self, *args, **kwargs):
        """Create the DemoFrame."""
        wx.Frame.__init__(self, *args, **kwargs)

        # Build the menu bar
        MenuBar = wx.MenuBar()

        FileMenu = wx.Menu()

        item = FileMenu.Append(wx.ID_EXIT, text="&Quit")
        self.Bind(wx.EVT_MENU, self.OnQuit, item)

        MenuBar.Append(FileMenu, "&File")
        self.SetMenuBar(MenuBar)

        # Add the Widget Panel
        self.Panel = DemoPanel(self)

        self.Fit()

    def OnQuit(self, event=None):
        """Exit application."""
        self.Close()

if __name__ == '__main__':
    app = wx.App()
    frame = DemoFrame(None, title="Micro App")
    frame.Show()
    app.MainLoop()

}}}

=== Comments ===

Put your comments here.

Please also feel free to add to this page, though if you want to change something, please discuss on the wxPython-users group first (unless you're RobinDunn).

----
/* Comment #1 */
For good python coding style in general: 

 * [[http://www.python.org/dev/peps/pep-0008/|PEP 8 Style Guide]]
 * [[http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html|Code Like a  Pythonista]]

Also note that wxPython uses getter and setter methods (e.g. {{{GetLabel(), SetLabel(str)}}}) because it is a wrapper for another language. For native python modules you should use {{{@property}}} instead. Look at this stack over-flow question: [[http://stackoverflow.com/questions/6618002/python-property-versus-getters-and-setters | properties ]] and the Python docs: [[http://docs.python.org/2/library/functions.html#property | property ]]. Of course, if you are writing a custom or extended wxPython class, use the wx style for consistency.

-- AnthonyGlaser <<DateTime(2013-05-11T16:15:53Z)>>
----


=== History ===

First Written 1/11/2006 by Chris Barker, with a lot of help from the wxPython-users mailing list.

Franz Steinhaeusler, 16. Jan. 2006:
  Added docstrings for __init__ methods.

14/1/2010 - Added StdDialogButtonSizer