MVC with Tkinter

Introduction

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.

Suddenly code

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()

Finished product

スクリーンショット 2020-08-29 16.25.14.png

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.

Commentary

What's going on?

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.

What does it mean to not know?

"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.


Digression

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

MVC with Tkinter
Become Santa with Tkinter
Programming with Python and Tkinter
Getting Started with Tkinter 2: Buttons
Working with tkinter and mouse
Screen switching / screen transition with Tkinter
Create Image Viewer with Tkinter
Let's make dice with tkinter
Run Label with tkinter [Python]
I measured BMI with tkinter
Easy GUI app with Tkinter Text
Async / await with Kivy and tkinter
[Tkinter] Control threads with Event object
[Python] Creating multiple windows with Tkinter
Play video with sound with python !! (tkinter / imageio)
Creating an image splitting app with Tkinter
Make GUI apps super easy with tkinter
Develop Windows apps with Python 3 + Tkinter (Preparation)
Create a GUI executable file created with tkinter
GUI image cropping tool made with Python + Tkinter
Create a matrix with PythonGUI (tkinter combo box)
Develop Windows apps with Python 3 + Tkinter (exe file)
How to use tkinter with python in pyenv
Upload images to S3 with GUI using tkinter
Iterative (recursive) processing with tkinter (displayed in order)
I tried playing with the calculator on tkinter