title: Setting value of Entry using tkinter, MVC and Observables
body: <p>I am trying to build a simple GUI using tkinter to read in CSV's and then run some text mining functions. I am having difficulty understand tkinter's callback function. The following code was created using this ToyMVC code.</p>
  
  <p>I am able to get the GUI to pop up but am having trouble getting the rightmost Entry widget (variable name = finalPathEntry) to update with the user-inputted text from the left Widget once the user presses the button.</p>
  
  <p>I would greatly appreciate any advice on how to move forward and what I am doing wrong.</p>
  
  <p>Best,</p>
  
  <pre><code>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.csvPath = Observable("")
  
      def addPath(self, value):
          self.csvPath.set(self.csvPath.get())
  
  
  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='Please input path to CSV').pack(side='left')
  
          self.pathEntry = tk.Entry(self, width=50)
          self.pathEntry.pack(side='left')
          self.addButton = tk.Button(self, text='Read CSV', width=8)
          self.addButton.pack(side='left')
          self.path = tk.StringVar()
          self.finalPathEntry = tk.Entry(self, width = 30, textvariable = self.path)
          self.finalPathEntry.pack(side='left')
  
      def setPath(self, value):
          self.path.set(str(value)) 
  
  
  class Controller:
      def __init__(self, root):
          self.model = Model()
          self.model.csvPath.addCallback(self.pathChanged)
          self.view1 = View(root)
          self.view1.minsize(width = 500, height = 500)
          self.view1.addButton.config(command=self.addPath)
          self.pathChanged(self.model.csvPath.get())
  
      def addPath(self):
          self.model.addPath(self.view1.pathEntry.get())
  
      def pathChanged(self, val):
          self.view1.setPath(val)
  
  
  if __name__ == '__main__':
      root = tk.Tk()
      root.withdraw()
      app = Controller(root)
      root.mainloop()
  </code></pre>
  
  <p>EDIT: Using the answer below, I have fixed my code. Here is the updated and working snippet:</p>
  
  <pre><code>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.csvPath = Observable("")
  
      def addPath(self, value):
          self.csvPath.set(self.csvPath.get())
  
  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='Please input path to CSV').pack(side='left')
          self.pathEntry = tk.Entry(self, width=50)
          self.pathEntry.pack(side='left')
          self.addButton = tk.Button(self, text='Read CSV', width=8)
          self.addButton.pack(side='left')
          self.path = tk.StringVar()
          self.finalPathEntry = tk.Entry(self, width = 30, textvariable = self.path)
          self.finalPathEntry.pack(side='left')
  
      def setPath(self, value):
          self.path.set(str(value))
  
  class Controller:
      def __init__(self, root):
          self.model = Model()
          self.model.csvPath.addCallback(self.pathChanged)
          self.view1 = View(root)
          self.view1.minsize(width = 500, height = 500)
          self.view1.addButton.config(command = self.addPath)
          self.pathChanged(self.model.csvPath.get())
  
      def addPath(self):
          self.model.addPath(self.view1.pathEntry.get())
  
      def pathChanged(self, val):
          self.view1.setPath(val)
  
  if __name__ == '__main__':
      root = tk.Tk()
      root.withdraw()
      app = Controller(root)
      root.mainloop()
  </code></pre>