views:

728

answers:

2

I am new to Python. I am writing an application using wxPython and I currently my code that generates a toolbar looks like this:

class Window(wx.Frame)
def __init__(self, parent, plot):
    wx.Frame.__init__(self, parent, wx.ID_ANY, "Name", size =(900, 600))
    self.Centre()

    self.toolbar = self.CreateToolBar(style=(wx.TB_HORZ_LAYOUT | wx.TB_TEXT))
    self.toolbar.SetToolBitmapSize((32,32))
    self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/fileopen.png'))
    self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/filesave.png'))
    self.toolbar.AddSeparator()
    self.toolbar.Realize()

I am trying to clean up the code a bit and I want the toolbar to have its own class so when I want to create a toolbar, I simply call it something like this:

toolbar = Toolbar()

My question is how can I rewrite it so it works like that? Currently my code looks like this:

class Toolbar():
    def __init__(self):
        self.toolbar = self.CreateToolBar(style=(wx.TB_HORZ_LAYOUT | wx.TB_TEXT))
        self.toolbar.SetToolBitmapSize((32,32))
        self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/fileopen.png'))
        self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/filesave.png'))
        self.toolbar.AddSeparator()
        self.toolbar.Realize()

I am not quite sure how 'self' works. Do I need to rewrite the init function? How do I fix it? Any help is greatly appreciated. Thanks

+1  A: 

Hi,

Instead of a class that sets up your toolbar, use a function. The function can be a member function of your Window that subclasses wx.Frame. That way, the toolbar will get Created from the correct window, and be attached the way you would expect.

The class that you're writing above would work, if it knew which wx.Frame (your class called Window) to connect the toolbar to. To get it to work you would have to pass the frame object to the toolbar creator class...

class Toolbar():
  def __init__(self, frame_to_connect_to):
    frame_to_connect_to.toolbar = frame_to_connect_to.CreateToolBar(style=(wx.TB_HORZ_LAYOUT | wx.TB_TEXT))
    frame_to_connect_to.toolbar.SetToolBitmapSize((32,32))
    frame_to_connect_to.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/fileopen.png'))
    frame_to_connect_to.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/filesave.png'))
    frame_to_connect_to.toolbar.AddSeparator()
    frame_to_connect_to.toolbar.Realize()

It looks like a quick fix... but really using a class to do this is not a good use of classes. (I'd even go so far as to say it was incorrect.)

Really, what would clean things up a bit would be just to move the toolbar stuff to its own member function:

class Window(wx.Frame)
  def __init__(self, parent, plot):
    wx.Frame.__init__(self, parent, wx.ID_ANY, "Name", size =(900, 600))
    self.Centre()
    self._init_toolbar()

  def _init_toolbar(self):
    self.toolbar = self.CreateToolBar(style=(wx.TB_HORZ_LAYOUT | wx.TB_TEXT))
    self.toolbar.SetToolBitmapSize((32,32))
    self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/fileopen.png'))
    self.toolbar.AddLabelTool(3, '', wx.Bitmap('GUI/icons/filesave.png'))
    self.toolbar.AddSeparator()
    self.toolbar.Realize()

You get all the benefits.

Jim Carroll
+1  A: 

Yes. Break your wxpython code into objects like this. It is much easier to maintain if you are going to code your GUI by hand (I do).

You need to subclass wx.ToolBar (which itself is a subclass of wx.ToolBarBase, and most of wx.ToolBar's functions are derived from that namespace):

class MyToolBar(wx.ToolBar):
    def __init__(self, parent, *args, **kwargs):
        wx.ToolBar.__init__(self, parent, *args, **kwargs)
        #note self here and not self.toolbar
        self.SetToolBitmapSize((32,32))
        #add other code here

Then in your __init__ for your wx.Frame call your toolbar:

class MyFrame(wx.Frame):
    def __init__(self, parent, *args, **kwargs):
        wx.Frame.__init__(self, parent, *args, **kwargs)
        #note that below, self refers to the wx.Frame
        #self(wx.Frame) = parent for the toolbar constructor
        toolbar = MyToolBar(self)

wxPython Style Guide

Another thing to note is that often the wxWidgets docs are much easier to navigate and to decipher.

DrBloodmoney