如何将模型动作传递给 Tkinter MVC 中的查看按钮?

Posted

技术标签:

【中文标题】如何将模型动作传递给 Tkinter MVC 中的查看按钮?【英文标题】:How to pass Model action to View button in Tkinter MVC? 【发布时间】:2018-02-21 14:31:54 【问题描述】:

我正在尝试使用 Tkinter 将 GUI 开发为 MVC 模式,但这种方式对我来说是新的。我在网上看到了很多例子,但我仍然更喜欢了解它是如何工作的。这就是为什么我只是编写一个简单的应用程序来获取它。

开始,我只有树文件 controller.py、view.py 和 model.py。第一个是 View 和 Model 之间的连接器,但最后一个从未相互链接。模型只包含方法/函数;和查看图形界面,我的意思是小部件。

问题是,如果 View 类(view.py)有一个没有命令的按钮,并且这个按钮应该执行的操作是在 Models 类(model.py)中,我必须为 Controller 类(controller.py)写什么? py) 获取此操作并将其分配给按钮?

view.py 文件:

#!/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 文件:

#!/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()

【问题讨论】:

你可以使用signal/slot的想法(例如PyPubSubPyDispatcher blinker)。您不妨看看 Ninad Sathaye 的《学习 Python 应用程序开发》一书的第 10 章。第 10 章使用tkinter 解释并实现了一种类型的 MVC。对于 MVC 的许多变体,您不妨参考 Stefano Borini 的书《理解模型-视图-控制器》。 【参考方案1】:

您可以在控制器 init() 函数中使用它:

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

这样您就不必在视图中使用命令。

我仍在试图弄清楚如何为菜单按钮执行此操作...因此,如果它对您来说是新的(就像对我一样),这可能会有点困难。

编辑: 根据要求,一个小样本:

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

【讨论】:

在这种情况下,一个最小的工作示例会有所帮助。 已经提供了一个例子。【参考方案2】:

如果按钮没有命令,那么什么都不会发生。 它需要有一个命令,调用控制器的功能。

然后,控制器将通过与模型通信或触发另一个视图来执行此命令。

由于按钮要调用控制器的功能,它需要意识到这一点。 假设您将它作为参数传递,并且您希望按钮触发controller.ActioncontrollerController 的(?)实例。

您的视图应如下所示:

class View():
    def __init__(self, master, controller):
        self.master = master
        self.controller = controller

        b = Button(master, text='Hello', command=self.controller.Action())
        b.pack()

然后,点击按钮将调用Action

【讨论】:

以上是关于如何将模型动作传递给 Tkinter MVC 中的查看按钮?的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC我想重定向到另一个将我的模型传递给它的动作,以获得正确的URL

如何将模型传递给具有其他参数的动作

如何序列化模型,将其传递给 ajax 请求中的 MVC 控制器

如何在 asp.net mvc 5 中返回模型和参数中的另一个动作?

MVC 4如何将模型属性列表从视图传递给Action

将模型传递给 ASP.NET Core MVC 中的视图