PyObject in Bind

Hallo people,
I have posted this note in the chats, but eventually nobody is online. Here is the question:

Hallo people, anybody able to give help on the Bind function?

I am trying to build up sort of “strange” architecture

I have a “main” file where I define frames, for instance

Then I make a “Widget builder” which is supposed to take care of button construction, for instance

data for the buttons are stored in a separate module which contains a dictionary: keys are button names and values are named tuples with e.g. labels and handlers.

The builder gets called from the “main” like: button1 = gc.ButtonBuilder(self, “button 1”)

The builder itself is a function in a separate module: def ButtonBuilder(parent, buttonName):

From that “ButtonBuilder” fetching the data from the data container and building a button in the parent frame (other module) is pretty trivial

It would be anyway nice to build, always from the builder, a handler to the button that binds the button to the handler method located in the controller module

I have a controller called GuiController made like that:

GuiController(object):

def OnTest(self, event):

print “Hei I have come up to here!”

Now, given that in the builder I have imported GuiController and instantiated it as gcontrol, it is pretty straigthforward having a handler function parsed out from my dictionary:

handler = getattr(gcontrol, button_data.handler)

(button_data.handler is the reference to my namedtuple in the gui data dictionary)

The problem is that the sytax of Bind is (event, handler, source,…), where handler is a so called “PyObject”

This means that if I place there my handler, which is gcontrol.OnTest() it doesn’t work.

I must place there just “The name”: gcontrol.OnTest

The only non-elegant way I am using to do that is:

name = “controller.” + str(handler.name)

parent.Bind(wx.EVT_BUTTON, eval(name), _button)

I hate that eval. Do anybody know a better way to do that???

I am just learning here… Attached you find the four files, it’s just work in progress.

Thanks in advance!

testguicommons.py.html (5.77 KB)

testguicontroller.py.html (1.79 KB)

testGuiData.py.html (2.65 KB)

senderreceivertest.py.html (6.38 KB)

The solution is simple and Pythonic:

self._panel = wx.Panel(parent=self, …)

self._button = wx.Button(parent=_panel, …)

self._button,Bind(event=wx.EVT_BUTTON, handler=self.OnTest)

Just be sure you put these lines in the scope of wx.Frame.init and you’re golden. :slight_smile:

Hei Bostjan,

Thanks so much for the explanation, although I think there was some misunderstanding due to the complex and fuzzy way I wrote things the first time. My problem was how to dynamically define the handler in a multi-module structure.

I think I have found the solution (I am a bit proud of it, being a self-teaching newbie programmer) and I think it could have some merit, so, for the interested I will explain it. I have found the error: it was that the contents of the dictionary in the module were unbound methods. Now I have instantiated them and all seems to work as I wanted.

I have a file that, for me, is the “controller” in a CMV structure. In this file I collect all the handlers of my system “widgets” (I am experimenting simply with buttons now):

#!/usr/bin/env python

import wx

class GuiController(object):

def OnTest(self, event):

    print "Hei I have come up to here!"

def OnTest2(self, event):

    print"This is the second button"

This file is called “testguicontroller.py”.

Then I have a file which contains the widget-buttons data. It is called “testguidata.py”. The important difference from my initial example is that I import there the controller and I create an instance of it. Then I insert in the dictionary its different methods. It’s bold underlined in the following code.

#!/usr/bin/env python

‘’’

Example module containing some gui data

‘’’

from testguicontroller import GuiController

from collections import namedtuple

c = GuiController()

BtData = namedtuple(“BtData”, “label handler”)

buttonData = {

    "button 1": BtData("test button", **c.OnTest**),

    "button 2": BtData("second test", **c.OnTest2**) #those are no longer strings but methods of the c instance.

         }

This is just a module with a top-level dictionary. It’s intended to contain just data and no behavior, therefore a class is not needed/suited.

Now, let’s imagine I have a main gui module, which contains:

  • app instance and initialization,

  • Frame definition

  • Possibly a lot of children, like classes, each one being a “page” of a notebook, …

…something as complex as I have in mind!!!

The idea is that you keep this “mainframe” as clean as possible, just “naming” the widgets/windows (buttons in this example) there, delegating their implementation (which in the case of buttons consists in instantiation of the wx.Button, the “Bind” to an event handler, and the event handler itself) somewhere else…

The magic there can be just calling (from within a frame, for instance) something like:

import testguicommons as gc

class myFrame(wx.Frame):

def __init__(self, parent, title):

    wx.Frame.__init__(self, parent, -1, title, pos = wx.DefaultPosition,

                      size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE)

    **button1 = gc.ButtonBuilder(self, "button 1")**

    **button2 = gc.ButtonBuilder(self, "button 2")**

    #layout

    sizer = wx.GridSizer(0,0,0,0)

    sizer.Add(button1)

    sizer.Add(button2)

    self.SetSizer(sizer)

So: the “mainframe module” just contains such “magic builders” and the layout definition.

Now, here it is how this “magic builder” works:

The file, as already implied in the import statement above is: “testguicommons.py” and here it goes: [In the next message because I am lost with formatting]

···

On Monday, February 17, 2014 1:19:47 AM UTC+1, Boštjan Mejak wrote:

The solution is simple and Pythonic:

self._panel = wx.Panel(parent=self, …)

self._button = wx.Button(parent=_panel, …)

self._button,Bind(event=wx.EVT_BUTTON, handler=self.OnTest)

Just be sure you put these lines in the scope of wx.Frame.init and you’re golden. :slight_smile:

So, here it goes:

#!/usr/bin/env python

import wx

import testGuiData

from testguicontroller import GuiController as gcontrol

controller = gcontrol()

def ButtonBuilder(parent, buttonName):

'''

This function builds button in every parent requesting to do so.

Data needed for button construction (label, position etc.) must be stored in the

testGuiData.buttonData dictionary.

'''

button_data = testGuiData.buttonData[buttonName] # retrieves the data from the dictionary

_button = wx.Button(parent, -1, button_data.label) # defines the button

parent.Bind(wx.EVT_BUTTON, button_data.handler, _button) # binds the button to the handler in the controller

return _button # returns the (bound) button to the parent "mainframe"

This one, now, is just a function in a module: data stay somewhere else (just “behavior”). And the function doesn’t need a “self” (would it be a “staticmethod” otherwise?? You teach me).

Now, what I have achieved here?

  1. I have a “mainframe” where I just have to “plan and implement” my GUI “architecture”. I need just to create “parents”, “name” windows/widgets to be constructed, laying them out e.g. in sizers.

  2. I have a file which basically just contains all the data needed to build windows/widgets, ordered into a dictionary, where I just order them by keys being the “name” of the widget I want to build up in the mainframe

  3. I have a controller, where I group all my handlers. Of course, now I will go on linking this controller to a “model” in my CMV structure.

  4. I have a “builder” which

  • gets the command of making a widget from the mainframe

  • gets the needed data from the data container

  • binds the widget to the handler which is constructed within the controller.

Now, if I want to make “my big project”, I just can go on orderly. When in my “mainframe” I need to add a widget/window, I just “call it in the mainframe”. Then I add the needed data to my dictionary. I define the handler (the “action”) into the controller, and … I don’t care of anything else: the builder makes all the rest. Cool???

At last, in “my big project” I will have things every one sorted out in their ordered place.

Can any good code master here around tell me if all this makes any sense or is just “newbie grumbling”? I am trying to learn the famous “design patterns”. Actually I cannot clearly recognize any in what I made! LOL! Is there anybody telling me if this is one?

Thanks a lot in advance!

Sorry people, in the builder above I noticed that (remnants of a previous version) the import and instantiation of testguicontroller/GuiController are completely useless. Ignore them!

···

On Monday, February 17, 2014 11:56:21 PM UTC+1, Fabio Spreafico wrote:

So, here it goes:

#!/usr/bin/env python

import wx

import testGuiData

from testguicontroller import GuiController as gcontrol

controller = gcontrol()

def ButtonBuilder(parent, buttonName):

'''
This function builds button in every parent requesting to do so.
Data needed for button construction (label, position etc.) must be stored in the
testGuiData.buttonData dictionary.
'''
button_data = testGuiData.buttonData[buttonName] # retrieves the data from the dictionary
_button = wx.Button(parent, -1, button_data.label) # defines the button
parent.Bind(wx.EVT_BUTTON, button_data.handler, _button) # binds the button to the handler in the controller
return _button # returns the (bound) button to the parent "mainframe"

This one, now, is just a function in a module: data stay somewhere else (just “behavior”). And the function doesn’t need a “self” (would it be a “staticmethod” otherwise?? You teach me).

Now, what I have achieved here?

  1. I have a “mainframe” where I just have to “plan and implement” my GUI “architecture”. I need just to create “parents”, “name” windows/widgets to be constructed, laying them out e.g. in sizers.
  1. I have a file which basically just contains all the data needed to build windows/widgets, ordered into a dictionary, where I just order them by keys being the “name” of the widget I want to build up in the mainframe
  1. I have a controller, where I group all my handlers. Of course, now I will go on linking this controller to a “model” in my CMV structure.
  1. I have a “builder” which
  • gets the command of making a widget from the mainframe
  • gets the needed data from the data container
  • binds the widget to the handler which is constructed within the controller.

Now, if I want to make “my big project”, I just can go on orderly. When in my “mainframe” I need to add a widget/window, I just “call it in the mainframe”. Then I add the needed data to my dictionary. I define the handler (the “action”) into the controller, and … I don’t care of anything else: the builder makes all the rest. Cool???

At last, in “my big project” I will have things every one sorted out in their ordered place.

Can any good code master here around tell me if all this makes any sense or is just “newbie grumbling”? I am trying to learn the famous “design patterns”. Actually I cannot clearly recognize any in what I made! LOL! Is there anybody telling me if this is one?

Thanks a lot in advance!

Hi, I didn’t go over what you wrote very carefully, but I wonder if you would be interested in some ~5yr old attempts at coming up with other ways to create a wxPython layout in a different way that reminded (perhaps erroneously?) of what you’re trying to do here:

One is from Stef Mientki (as inspired by NorbertK):
http://wxpython-users.1045709.n5.nabble.com/Best-practice-to-rganize-the-code-tp2362917p2362938.html

The other was referenced by Peter Damoc in response to Stef:
http://code.google.com/p/wxpita/

···

On Mon, Feb 17, 2014 at 6:13 PM, Fabio Spreafico spreafab@gmail.com wrote:

Sorry people, in the builder above I noticed that (remnants of a previous version) the import and instantiation of testguicontroller/GuiController are completely useless. Ignore them!

On Monday, February 17, 2014 11:56:21 PM UTC+1, Fabio Spreafico wrote:

So, here it goes:

#!/usr/bin/env python

import wx

import testGuiData

from testguicontroller import GuiController as gcontrol

controller = gcontrol()

def ButtonBuilder(parent, buttonName):

'''
This function builds button in every parent requesting to do so.
Data needed for button construction (label, position etc.) must be stored in the
testGuiData.buttonData dictionary.
'''
button_data = testGuiData.buttonData[buttonName] # retrieves the data from the dictionary
_button = wx.Button(parent, -1, button_data.label) # defines the button
parent.Bind(wx.EVT_BUTTON, button_data.handler, _button) # binds the button to the handler in the controller
return _button # returns the (bound) button to the parent "mainframe"

This one, now, is just a function in a module: data stay somewhere else (just “behavior”). And the function doesn’t need a “self” (would it be a “staticmethod” otherwise?? You teach me).

Now, what I have achieved here?

  1. I have a “mainframe” where I just have to “plan and implement” my GUI “architecture”. I need just to create “parents”, “name” windows/widgets to be constructed, laying them out e.g. in sizers.
  1. I have a file which basically just contains all the data needed to build windows/widgets, ordered into a dictionary, where I just order them by keys being the “name” of the widget I want to build up in the mainframe
  1. I have a controller, where I group all my handlers. Of course, now I will go on linking this controller to a “model” in my CMV structure.
  1. I have a “builder” which
  • gets the command of making a widget from the mainframe
  • gets the needed data from the data container
  • binds the widget to the handler which is constructed within the controller.

Now, if I want to make “my big project”, I just can go on orderly. When in my “mainframe” I need to add a widget/window, I just “call it in the mainframe”. Then I add the needed data to my dictionary. I define the handler (the “action”) into the controller, and … I don’t care of anything else: the builder makes all the rest. Cool???

At last, in “my big project” I will have things every one sorted out in their ordered place.

Can any good code master here around tell me if all this makes any sense or is just “newbie grumbling”? I am trying to learn the famous “design patterns”. Actually I cannot clearly recognize any in what I made! LOL! Is there anybody telling me if this is one?

Thanks a lot in advance!

You received this message because you are subscribed to the Google Groups “wxPython-users” group.

To unsubscribe from this group and stop receiving emails from it, send an email to wxpython-users+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

Hi,

···

On 18/02/2014 07:00, C M wrote:

Hi, I didn't go over what you wrote very carefully, but I wonder if you would be interested in some ~5yr old attempts at coming up with other ways to create a wxPython layout in a different way that reminded (perhaps erroneously?) of what you're trying to do here:

One is from Stef Mientki (as inspired by NorbertK):
http://wxpython-users.1045709.n5.nabble.com/Best-practice-to-rganize-the-code-tp2362917p2362938.html

The other was referenced by Peter Damoc in response to Stef:
Google Code Archive - Long-term storage for Google Code Project Hosting.

Another thread was "Separating GUI code from Logic" about 3 years ago, I ended up using a lot what Kevin explained in that thread and I use the wx.lib.sized_controls he did to reduce the amount of sizer related code a lot.

Werner

Che and Werner,

thank you for your replies. Yes I had (also a cursory) look at the material you have linked here, and the “Separating GUI code from logic” was one of the “inspirators” of my solution.

Surely, as a “learning pupil” I re-invented the wheel. This is a sad fate of many people, I fear, due to the fact that an organic and easily accessible reference on wxPython architectural design is quite rare, I fear. At least I have found nothing usable in the context of planning a rich GUI application with many components. The refactoring examples on Dunn’s or Precord’s books are quite small. Both deal with single, 100-lines long files and a couple of widgets. MVC or MVP examples are also teaching a lot about the structure of the three components, but when it comes down to the “view” this is a pretty classical, “spaghetti prone” design.

Could you eventually point me to some good reference about NON-web, rich-client architecture in python + wx?

The wxpita project was probably a nice one, but now clearly discontinued. Basically it is a wrapper architecture around wx. I have the feeling I am also building one. It costed me much sweat and thinking time, but now I have it in place (at least: clear in my head), so I think I can go on from there.

Many thanks again!

···

On Tuesday, February 18, 2014 9:44:25 AM UTC+1, werner wrote:

Hi,

On 18/02/2014 07:00, C M wrote:

Hi, I didn’t go over what you wrote very carefully, but I wonder if
you would be interested in some ~5yr old attempts at coming up with
other ways to create a wxPython layout in a different way that
reminded (perhaps erroneously?) of what you’re trying to do here:

One is from Stef Mientki (as inspired by NorbertK):

http://wxpython-users.1045709.n5.nabble.com/Best-practice-to-rganize-the-code-tp2362917p2362938.html

The other was referenced by Peter Damoc in response to Stef:

http://code.google.com/p/wxpita/

Another thread was “Separating GUI code from Logic” about 3 years ago, I
ended up using a lot what Kevin explained in that thread and I use the
wx.lib.sized_controls he did to reduce the amount of sizer related code
a lot.

Werner