Model View Presenter GUI pattern?
Chris Liechti
cliechti at gmx.net
Thu Dec 13 18:42:57 EST 2001
[posted and mailed]
george young <gry at ll.mit.edu> wrote in
news:20011213172833.0bfac3c7.gry at ll.mit.edu:
> Is anyone using the Model View Presenter GUI framework/pattern in
> python? I've been reading bits about it, and it sounds quite
> attractive.
>
> I've started trying to write a simple MVP module as a basis for an
> application. The hardest part is dealing with the overall structure:
> my app deals with a big structured data object and it's hard to picture
> how the parallel trees of models, views, and presenters all get
> instantiated and linked.
>
> Below I include my baby mvp.py file (using pygtk) for
> comment/discussion. Any comments of design/implementation/style etc.
> are very welcome.
>
> A few mvp references for the curious:
> http://www.object-arts.com/Lib/EducationCentre4/htm/modelviewpresenter.h
> tm
> http://www.object-arts.com/EducationCentre/Overviews/ModelViewPresenter.
> htm http://www-106.ibm.com/developerworks/library/mvp.html
>
>
> import gtk
> class Topw(gtk.GtkWindow):
> def __init__(self):
> gtk.GtkWindow.__init__(self, gtk.WINDOW_TOPLEVEL)
> self.connect("destroy", gtk.mainquit)
> self.connect("delete_event", gtk.mainquit)
>
>
> class Observable:
> def __init__(self):
> self.observers = []
> def register(self, o):
> self.observers.append(o)
> def un_register(self, o):
> self.observers.remove(o)
> def notify(self):
> for o in self.observers:
> o.update(self)
i prefer "notify(self, *args, **kargs)" and o.update(self, *args, **kargs)
then you can give along detailed information on changes e.g. when your
model is a table you can pass the row and column of the changed cell.
> class Observer:
> '''Just for clarity, not really needed.'''
> def update(self): pass
i would throw an exception here, so that you see when you forgot to
override update somewhere.
> class Model(Observable):
> def __init__(self, value=None):
> Observable.__init__(self)
> self.set(value)
> def get(self):
> return self._value
> def set(self, v):
> self._value = v
shouldn't notify() be called here?
> def str(self):
> return `self.get()`
>
>
> class IntegerModel(Model):
> def __init__(self, i):
> Model.__init__(self, i)
> def set(self, i):
> self._value = int(i)
notify()...
>
> class IntegerView(gtk.GtkEntry, Observer):
> def __init__(self):
> gtk.GtkEntry.__init__(self)
>
> def set(self, x):
> self.set_text(`x`)
>
> def clear(self):
> self.delete_text(0, -1)
>
> def update(self, mod):
> self.set(mod.get())
>
>
> class IntegerPresenter:
> def __init__(self, i=None):
> self.view = IntegerView()
> self.model = IntegerModel(i)
> self.model.register(self.view)
> self.view.connect('changed', self.changed)
>
> def changed(self, v):
> try:
> self.model.set(int(v.get_text()))
> except ValueError:
> gtk.gdk_beep()
>
>
> if __name__ == '__main__':
> pres = IntegerPresenter(33)
> topw = Topw()
> topw.add(pres.view)
> topw.show_all()
> gtk.mainloop()
>
there yould also be an diffrent solution using a proxy pattern. the proxy
class implements __getattr__ and __setattr__, gets its data from the
wrapped class, but also notifies all registred observers on a __setattr__
call.
chris
--
Chris <cliechti at gmx.net>
More information about the Python-list
mailing list