Adding method to a class on the fly

John Henry john106henry at hotmail.com
Sun Jun 24 17:05:13 EDT 2007


On Jun 24, 12:40 pm, John Henry <john106he... at hotmail.com> wrote:
> On Jun 24, 1:19 am, John Henry <john106he... at hotmail.com> wrote:
>
>
>
> > On Jun 23, 6:24 pm, Steven D'Aprano
>
> > <s... at REMOVE.THIS.cybersource.com.au> wrote:
> > > On Sat, 23 Jun 2007 12:31:39 -0700, John Henry wrote:
> > > > it works fine but PythonCard isn't calling this function when I
> > > > clicked on the button.
>
> > > I think you need to take this question onto a PythonCard list. I have no
> > > idea how PythonCard decides which method to call.
>
> > > --
> > > Steven.
>
> > I did.  I am not sure I'll get an answer though.
>
> > Thanks for the help.
>
> Upon further investigation, I found the problem.
>
> Pythoncard is relying on the __name__ attribute and that's why it
> didn't know about the newly careated function.  I can not set that
> attribute directly, of course, since it's a readonly attribute.  Need
> other workaround.
>
> The author of Pythoncard has responded and so I am shifting this
> thread over to the Pythoncard list.
>
> Thanks again for all the help.  I learned a few things about Python
> through this exercise.


Okay, just to complete the record - in case anybody tries to google
for a solution to add control to PythonCard at run time, here's a
complete code:

#!/usr/bin/python

"""
__version__ = "$Revision: 1.6 $"
__date__ = "$Date: 2004/08/17 19:46:06 $"
"""

import new

from PythonCard import log
from PythonCard import model
from PythonCard.model import SetInitParam

rsrc = {'application':{'type':'Application',
          'name':'Minimal',
    'backgrounds': [
    {'type':'Background',
          'name':'bgMin',
          'title':'Minimal PythonCard Application',
          'size':(200, 300),
         'components': [

] # end components
} # end background
] # end backgrounds
} }

class Background_Dynamic(model.Background):

    def __init__(self, aParent, aBgRsrc,
SetInitParamFct=SetInitParam):
        model.Background.__init__(self, aParent, aBgRsrc,
SetInitParamFct)

    def addHandler(self, aMethod):
        # Add the Handler to our Handler list.
        if aMethod.name not in self._handlers:
            log.debug("addHandler: " + aMethod.name)
            #self._handlers[aMethod.name] = event.Handler(aMethod)
            self._handlers[aMethod.name] = aMethod

    def mouseclick_factory(self, name):
        def function(self, background, event):
            self.mouseclick_factory("Button"+str(int(name[-1:])+1))
        function.name = "on_%s_mouseClick" % name
        method = new.instancemethod(function, self, self.__class__)
        setattr(self, function.name, method)
        self.addHandler(method)
        self.components[name] = {'type':'Button',
                                     'name':name,
                                     'label':name,
                                     'position':(5,
5+int(name[-1:])*30),
                                     'text':name}
        return function

class Minimal(Background_Dynamic):
    def on_initialize(self, event):
        self.components['field1'] =
{'type':'TextField','name':'field1','position':(5, 5),'size':(150,
-1),'text':'Hello PythonCard'}
        self.mouseclick_factory("Button1")

if __name__ == '__main__':
    app = model.Application(Minimal, None, rsrc)
    app.MainLoop()


It goes to show how flexible and powerful PythonCard is.  Too bad it
doesn't draw the attention of more new comers.




More information about the Python-list mailing list