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()
Few Related Post you might like
Pingback: Python:Best way to structure a tkinter application – IT Sprite
Pingback: 构造一个标准应用最好的方式 – CodingBlog
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
LikeLike
See this gist for a better example of separating the GUI dependencies
This file contains 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
controller.py
hosted with ❤ by GitHub
This file contains 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
main.py
hosted with ❤ by GitHub
This file contains 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
model.py
hosted with ❤ by GitHub
This file contains 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
side_panel.py
hosted with ❤ by GitHub
This file contains 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
view.py
hosted with ❤ by GitHub
LikeLiked by 1 person
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
LikeLike
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
LikeLike
Thanks for your code .
I am currently getting error:
AttributeError: ‘_tkinter.tkapp’ object has no attribute ‘deconify’
LikeLike
Hi Satish which version of python and tk are you using? This code is tested in 2.7
LikeLike
I am currently using python 3.6.Could please about why we using root.deconify and what is the purpose of that?
LikeLike
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
LikeLike
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()
LikeLiked by 1 person
Thanks Travis!!
LikeLike
Receiving error no module named numpy.testing. python 3.7 with numpy install through pip
LikeLike
Pingback: python - Modo migliore per strutturare un tkinter applicazione?
Pingback: An Example of Model View Controller Design Pattern with Tkinter Python 3 | SukhbinderSingh.com
Pingback: How to properly implement Tkinter module for software development? - PhotoLens
Pingback: Resolved: Is the relationship between a View and a Controller in MVC really just a Strategy pattern? - Daily Developer Blog
Pingback: Best way to structure a tkinter application? – Code D3