【问题标题】:tkinter- Passing entry widget value to another classtkinter- 将条目小部件值传递给另一个类
【发布时间】:2021-05-07 18:11:17
【问题描述】:

我已经从较早的问题中改编了这段代码,该问题巧妙地保留了导航框架,但根据按下的按钮更改了内容框架。登录页面有一个条目小部件。我想将它的值(例如“Paul”说)转移到 Play Game 框架,所以它说“这是游戏页面 Paul”。如果有人可以提供帮助,我不知道如何使用这种特殊设置。

import tkinter as tk

class Page(tk.Frame):
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)

    def show(self):
        self.lift()

    

class Page1(Page):
   def __init__(self, *args, **kwargs):
       
       Page.__init__(self, *args, **kwargs)
       
       label = tk.Label(self, text="This is the log in page ")
       username=tk.Entry(self)
      
       label.pack(side="top", pady=30, fill="both")
       username.pack()
       

class Page2(Page):
   def __init__(self, *args, **kwargs):
       Page.__init__(self, *args, **kwargs)

       label = tk.Label(self, text="This is the register page")
       label.pack(side="top", pady=30,fill="both")

class Page3(Page):
   def __init__(self, *args, **kwargs):
       
       
       Page.__init__(self, *args, **kwargs)
       label = tk.Label(self, text="This is the game page ") #+user
       label.pack(side="top",pady=30, fill="both")

class MainView(tk.Frame):
    
    def __init__(self, *args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        
        p1 = Page1(self)
        p2 = Page2(self)
        p3 = Page3(self)
        
        buttonframe = tk.Frame(self)
        container = tk.Frame(self)
        buttonframe.pack(side="left", fill="x", expand=False)
        buttonframe.configure(bg="red")
        container.pack(side="top", fill="both", expand=True)
        
        p1.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p2.place(in_=container, x=0, y=0, relwidth=1, relheight=1)
        p3.place(in_=container, x=0, y=0, relwidth=1, relheight=1)

        b1 = tk.Button(buttonframe, text="Log In", width=8, command=p1.lift)
        b2 = tk.Button(buttonframe, text="Register",width=8, command=p2.lift)
        b3 = tk.Button(buttonframe, text="Play Game",width=8, command=p3.lift)

        b1.pack(padx=10,pady=10)
        b2.pack(padx=10,pady =10)
        b3.pack(padx=10,pady=10)

        p1.show()

if __name__ == "__main__":
    
    root = tk.Tk()
    main = MainView(root)
    main.pack(side="top", fill="both", expand=True)
    root.wm_geometry("400x400")
    root.mainloop()

【问题讨论】:

  • 您需要保留对tk.Entry 和所有Page 对象的引用。而不是username=tk.Entry(self) 使用self.username = tk.Entry(self)。这样您以后可以使用self.username 访问它,并且您可以使用self.username.get() 获取tk.Entry 的内容。

标签: python tkinter


【解决方案1】:

您需要提供一种机制,让每个页面都可以访问其他页面。您还需要确保您需要访问的数据可作为实例属性使用。

控制器

通常,前者是通过通常称为控制器的东西来完成的。在这种情况下,这将是MainView,或一个新类。由于MainView 负责创建页面,它还可以负责授予对每个页面的访问权限,这可以通过在创建页面时保存对它们的引用来实现。

看起来像这样:

class MainView(tk.Frame):
    
    def __init__(self, *args, **kwargs):
        ...            
        self.p1 = Page1(self)
        self.p2 = Page2(self)
        self.p3 = Page3(self)
        ...

在每个页面中使用控制器

页面被赋予了对MainView 实例的引用,因此他们可以使用它来获取他们需要的数据。它看起来像这样:

class Page1(Page):
   def __init__(self, *args, **kwargs):
   
       Page.__init__(self, *args, **kwargs)
   
       self.controller = args[0]
       ...
       self.username=tk.Entry(self)
       ...

当您在每个页面中重复该模式时,每个页面都可以通过控制器访问每个其他页面:self.controller.p1self.controller.p2 等。这样,Page3 可以访问Page1 的用户名类似于self.controller.p1.username

这是在不同对象之间共享数据的基本机制。

约束

请注意,在您创建页面 3 时,用户将没有机会填写用户名,因此用户名将为空。您必须添加一些逻辑才能知道用户何时登录。

解决这个问题的一个简单方法是给每个页面一个show 方法。 show 方法负责提升页面并更新它的小部件。它可能看起来像这样:

class Page3(Page):
    def __init__(self, *args, **kwargs):
        Page.__init__(self, *args, **kwargs)
        self.controller = args[0]
        self.label = tk.Label(self, text="")
        self.label.pack(side="top",pady=30, fill="both")

    def show(self):
        user = self.controller.p1.username.get()
        self.label.configure(text=f"This is the game page for {user}")
        self.lift()

然后你需要修改你的按钮来调用show方法:

b1 = tk.Button(..., command=self.p1.show)
b2 = tk.Button(..., command=self.p2.show)
b3 = tk.Button(..., command=self.p3.show)

总结

拥有控制器是协调对象之间通信的便捷方式。而不是每个对象都必须直接与所有其他对象链接,它们只需要对控制器的引用。然后,控制器成为唯一与其他所有小部件直接连接的对象。

这不是视图/控制器模式的最佳实现,但希望它能提供基本概念的概念。

【讨论】:

  • 感谢您的回答和 Bryan 的完整解释。杰出的!我不会理解添加行 self.controller = args[0]。我想通过阅读您的其他帖子,更好的方法是创建一个将共享数据保存在列表中的类?
猜你喜欢
  • 2020-02-21
  • 1970-01-01
  • 2014-02-24
  • 2015-02-06
  • 2016-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多