An Example of Model View Controller Design Pattern with Tkinter Python

tkiniter_python_mvc_example
Model-view-controller (MVC) is the design pattern for successfully and efficiently relating the user interface to underlying data models.

This is a useful pattern for the reuse of object code and a pattern that allows to significantly reduce the time it takes to develop applications with user interfaces.

I have used MVC pattern in my ICP App and the STL viewer but most of my scientific computing GUI is based on tkinter since its readlily available in standard pythan installation, so had this very basic MVC based framework for quick prototypes.



# -*- coding: utf-8 -*-
 
"""
Created on Feb 18 10:30:38 2014

@author: Sukhbinder Singh

A basic python example of Model–view–controller (MVC), a software design pattern for implementing user interfaces for scientific application.

Mainly written as a quick start framework to quickly implement tkinter based GUI for prototypes for my personal and 


"""

import Tkinter as Tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np



class Model():

    def __init__(self):
        self.xpoint=200
        self.ypoint=200
        self.res = None
 
 
    def calculate(self):
        x,y=np.meshgrid(np.linspace(-5,5,self.xpoint),np.linspace(-5,5,self.ypoint))
        z=np.cos(x**2*y**3) 
        self.res = {"x":x,"y":y,"z":z}

class View():
    def __init__(self, master):
        self.frame = Tk.Frame(master)
        self.fig = Figure( figsize=(7.5, 4), dpi=80 )
        self.ax0 = self.fig.add_axes( (0.05, .05, .90, .90), axisbg=(.75,.75,.75), frameon=False)
        self.frame.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1)
        self.sidepanel=SidePanel(master)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
        self.canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        self.canvas.show()

class SidePanel():
    def __init__(self, root):
        self.frame2 = Tk.Frame( root )
        self.frame2.pack(side=Tk.LEFT, fill=Tk.BOTH, expand=1)
        self.plotBut = Tk.Button(self.frame2, text="Plot ")
        self.plotBut.pack(side="top",fill=Tk.BOTH)
        self.clearButton = Tk.Button(self.frame2, text="Clear")
        self.clearButton.pack(side="top",fill=Tk.BOTH)
 
class Controller():
    def __init__(self):
        self.root = Tk.Tk()
        self.model=Model()
        self.view=View(self.root)
        self.view.sidepanel.plotBut.bind("<Button>",self.my_plot)
        self.view.sidepanel.clearButton.bind("<Button>",self.clear)
 
    def run(self):
        self.root.title("Tkinter MVC example")
        self.root.deiconify()
        self.root.mainloop()
        
    def clear(self,event):
        self.view.ax0.clear()
        self.view.fig.canvas.draw()
 
    def my_plot(self,event):
        self.model.calculate()
        self.view.ax0.clear()
        self.view.ax0.contourf(self.model.res["x"],self.model.res["y"],self.model.res["z"])
        self.view.fig.canvas.draw()
 


if __name__ == '__main__':
    c = Controller()
    c.run()


Advertisements

12 thoughts on “An Example of Model View Controller Design Pattern with Tkinter Python

  1. Pingback: Python:Best way to structure a tkinter application – IT Sprite

  2. Pingback: 构造一个标准应用最好的方式 – CodingBlog

  3. The whole point of separating the GUI components is so that the controller doesn’t need to have any knowledge of the GUI. It shoulw only call functions/methods in the View object.
    the Controller should not be dealing with these GUI details.
    self.view.sidepanel.plotBut.bind(“”, self.my_plot)
    self.view.sidepanel.clearButton.bind(“”, self.clear)
    clear() and my_plot() must not be in the controller, they should be hidden in the View object

    Like

      • Hi Tony,, just saw this. I think the view and model are not separate in the implementation that is in the above gist and if the model changes, the view will need to change… . Will check this in detail… thanks for sharing!!.

        Cheers

        Like

    • Hi Tony

      Thanks for your feedback.

      As the post states, this is a very basic example to create quick prototypes, so you might be right.

      But what I have learned from static typed languages is that you define the model and views as complete separate entities, and the controller takes an instantiation of both model and views as parameters. If nothing breaks and the controller does all of the communication then yes, an application is MVC.

      Not necessary for the presented simple and quick prototypes but we might look at other design patterns such as Singleton, Factory and others that can help address your points.

      Have you tried anything better? I will be happy to learn a simple way to achieve this.

      Many thanks for reading and commenting
      Sukhbinder

      Like

  4. Thanks for your code .

    I am currently getting error:
    AttributeError: ‘_tkinter.tkapp’ object has no attribute ‘deconify’

    Like

    • The purpose of deconify to force detraw of the window. You can comment it. Should not affect your functionality. Please refer to Tkinter python 3 documentation. I think you should get an equivalent keyword if you need it. Thanks

      Like

  5. If you want this to work with Python 3.6, make these changes:
    1. Change import Tkinter as Tk
    TO:
    import tkinter as Tk

    2. Change self.ax0 = self.fig.add_axes( (0.05, .05, .90, .90), axisbg=(.75,.75,.75), frameon=False)
    TO:
    self.ax0 = self.fig.add_axes( (0.05, .05, .90, .90), facecolor=(.75,.75,.75), frameon=False)

    3. Change self.canvas.show()
    TO:
    self.canvas.draw()

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s