How to pass Model action to View button in Tkinter MVC?

Viewed 2281

I'm trying to get used developing GUIs as MVC pattern with Tkinter but it's new for me this way. I've seen a lot of examples on the web but I still prefer to understand how it works. That's why I'm just programming a simple app to get it.

Starting, I have just tree files controller.py, view.py, and model.py The first one is the connector between View and Model but these last ones are never linked each other. Model contains just methods/functions; and View the graphic interface, I mean the widgets.

The thing is that if View class (view.py) has a button without command, and the action this button should execute is in Models class (model.py), what do I have to write for Controller class (controller.py) get this action and asign it to the button?

view.py file:

#!/usr/bin/python
# -*- coding:UTF-8 -*-

from Tkinter import*

class View():
    def __init__(self, master):
        self.master = master
        master.title("MAIN GUI")
        master.geometry("400x200")
        l = Label(master, text="TITLE SCREEN")
        l.pack()
        b = Button(master, text='Hello')
        b.pack()

model.py file:

#!/usr/bin/python
# -*- coding:UTF-8 -*-

from Tkinter import*
from tkMessageBox import*

class Model():
    def __init__(self):
        pass
        #Greeting() #I don't know if this should be here.

    def Greeting(self):
        print "Hello world"

    def Alert(self):
        showinfo ('msg', "Hello world")

controller.py:

#!/usr/bin/python
# -*- coding:UTF-8 -*-

from view import*
from model import*

class Controller():
    def __init__(self, master):
        View(root)
        Model()
        View.b.config(command=Model.Greeting)
        #View.b.config(command=self.Action)

    def Action(self):
        Model.Greeting()

if __name__ == "__main__":
    root = Tk()
    View(root)
    root.mainloop()
2 Answers

You can use this in the controllers init() function:

self.view.b.bind("<Button>",self.action)

That way you don't have to use a command in the view.

I'm still trying to figure out how to do this for menubuttons... so this might be a bit of a struggle if it's new for you (like it is for me).

Edit: As requested, a small sample:

import tkinter as tk

# Data stuff
class Model():

    def __init__(self):
        pass          


# GUI
class View():

    def __init__(self, master):
        self.master = master
        self.b = tk.Button(self.master, text="quit")
        self.b.pack()

# Logic of the app
class Controller():

    def __init__(self):
        self.root = tk.Tk()
        self.model=Model()
        self.view=View(self.root)
        self.view.b.bind("<Button>",self.action)
        self.run()

    def run(self):
        self.root.mainloop()

    def action(self,event):
        self.root.destroy()


if __name__ == '__main__':
    c = Controller()
Related