Created
September 29, 2017 15:28
-
-
Save ajfigueroa/c2af555630d1db3efb5178ece728b017 to your computer and use it in GitHub Desktop.
Copy of Tkinter ToyMVC Model (from http://web.archive.org/web/20170205072049/http://tkinter.unpythonic.net/wiki/ToyMVC)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##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