MVC (Model-View-Controller) in this article refers to separating functions according to the following policy. ** Model **: I don't know View or Controller. Just do the calculation straightforwardly. ** View **: I don't know Model or Controller. Only in pursuit of beauty. ** Controller **: A divine position that knows both Model and View. It bridges Model and View.
I don't know what the number is, Surprisingly, I thought that there was not much information on MVC that follows the above policy, so I will write it as an article.
import tkinter as tk
class Model:
def __init__(self):
self.val = tk.IntVar(0)
def add_one(self):
self.val.set(self.val.get() + 1)
def reset(self):
self.val.set(0)
class View(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.value_label = tk.Label(self)
self.add_one_btn = tk.Button(self, text="ADD ONE")
self.reset_btn = tk.Button(self, text="RESET")
self.value_label.pack()
self.add_one_btn.pack()
self.reset_btn.pack()
self.pack()
class Controller:
def __init__(self, root):
self.model = Model()
self.view = View(root)
# Binding
self.view.value_label.config(textvariable=self.model.val)
# Callback
self.view.add_one_btn.config(command=self.model.add_one)
self.view.reset_btn.config(command=self.model.reset)
if __name__ == "__main__":
root = tk.Tk()
app = Controller(root)
root.mainloop()
When you press the ADD ONE button, the number above will increase by one. Press the RESET button to return the number above to 0.
Model
tk.IntVar ()
is a very convenient one. I'm using this instead of a regular int.
There are also tk.DoubleVar ()
, tk.BooleanVar ()
, and tk.StringVar ()
depending on the data type.
Just note that you need to use get () / set () to exchange values, and let the calculation go straight.
View View only cares about the appearance and creates components. Nothing is set here for the variable part (label text).
Controller
Controller knows both Model and View, so you can do whatever you want.
self.view.value_label.config(textvariable=self.model.val)
Here, IntVar () of Model is assigned to the label component that has emptied the text of View.
By doing this, the variables of Model and View will be synchronized, and if you change the value in Model, it will be automatically reflected in View.
In addition, the processing when each button is pressed is also assigned by the Controller.
"Model doesn't know View or Controller" simply means that Model doesn't have an instance of View or Controller.
For example, suppose you implement the following so that Model has View.
class Model:
def __init__(self, view):
self.val = 0
self.view = view
This way, when the value of the Model changes, you can tell the View about the change. For example
class Model:
#・ ・ ・
def add_one(self):
self.val += 1
self.view.label["text"] = str(self.val) #Reflect the value in view
It looks pretty easy and you might think it's better than the first code. But actually, the burden on the person who implements Model is increasing > < With this implementation, the person in charge of Model needs to know the following for this kind of addition process.
etc
There is also a risk of destroying the View if the Model has a View. It can be destroyed in one shot.
class Model:
#・ ・ ・
def balse(self):
self.view = None
Great power comes with great responsibility. I want to have as little power as possible.
So Let's clarify the division of roles with MVC and minimize the burden and responsibility.
I don't have much experience in creating GUIs, so I don't know which library is better. I've only used tkinter in python, It would be helpful if you could tell me what is good about wxpython and kivy.
Recommended Posts