Skip to content

Instantly share code, notes, and snippets.

@zahirkelloud
Forked from ajfigueroa/toymvc_example.py
Created December 25, 2019 20:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zahirkelloud/df758c6b0b53c0d53ad4f47bd76b7925 to your computer and use it in GitHub Desktop.
Save zahirkelloud/df758c6b0b53c0d53ad4f47bd76b7925 to your computer and use it in GitHub Desktop.
##Some points to mention...
##
##The model knows nothing about the view or the controller.
##The view knows nothing about the controller or the model.
##The controller understands both the model and the view.
##
##The model uses observables, essentially when important data is changed,
##any interested listener gets notified through a callback mechanism.
##
##The following opens up two windows, one that reports how much money you
##have, and one that has two buttons, one to add money and one to remove
##money.
##
##The important thing is that the controller is set up to monitor changes
##in the model. In this case the controller notices that you clicked a
##button and modifies the money in the model which then sends out a
##message that it has changed. The controller notices this and updates
##the widgets.
##
##The cool thing is that anything modifying the model will notify the
##controller. In this case it is the controller modifying the model, but it
##could be anything else, even another controller off in the distance
##looking at something else.
##
##The main idea is that you give a controller the model and view that it
##needs, but the model's can be shared between controllers so that when
##the model is updated, all associated views are updated. -Brian Kelley
##
## following is a Tkinter approximation of the original example.
import Tkinter as tk
class Observable:
def __init__(self, initialValue=None):
self.data = initialValue
self.callbacks = {}
def addCallback(self, func):
self.callbacks[func] = 1
def delCallback(self, func):
del self.callback[func]
def _docallbacks(self):
for func in self.callbacks:
func(self.data)
def set(self, data):
self.data = data
self._docallbacks()
def get(self):
return self.data
def unset(self):
self.data = None
class Model:
def __init__(self):
self.myMoney = Observable(0)
def addMoney(self, value):
self.myMoney.set(self.myMoney.get() + value)
def removeMoney(self, value):
self.myMoney.set(self.myMoney.get() - value)
class View(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self, master)
self.protocol('WM_DELETE_WINDOW', self.master.destroy)
tk.Label(self, text='My Money').pack(side='left')
self.moneyCtrl = tk.Entry(self, width=8)
self.moneyCtrl.pack(side='left')
def SetMoney(self, money):
self.moneyCtrl.delete(0,'end')
self.moneyCtrl.insert('end', str(money))
class ChangerWidget(tk.Toplevel):
def __init__(self, master):
tk.Toplevel.__init__(self, master)
self.addButton = tk.Button(self, text='Add', width=8)
self.addButton.pack(side='left')
self.removeButton = tk.Button(self, text='Remove', width=8)
self.removeButton.pack(side='left')
class Controller:
def __init__(self, root):
self.model = Model()
self.model.myMoney.addCallback(self.MoneyChanged)
self.view1 = View(root)
self.view2 = ChangerWidget(self.view1)
self.view2.addButton.config(command=self.AddMoney)
self.view2.removeButton.config(command=self.RemoveMoney)
self.MoneyChanged(self.model.myMoney.get())
def AddMoney(self):
self.model.addMoney(10)
def RemoveMoney(self):
self.model.removeMoney(10)
def MoneyChanged(self, money):
self.view1.SetMoney(money)
if __name__ == '__main__':
root = tk.Tk()
root.withdraw()
app = Controller(root)
root.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment