Tkinter 文本小部件 - 控制器中的变量

Tkinter Text Widget - variable in controller

我有一个带有多个框架和不同小部件的小型 GUI。我能够使所有变量成为全局变量,并在控制器中可用,但我被困在文本小部件上。有什么建议吗?

这里只是举个例子,文本小部件在class“PageOne”,打印功能在“PageTwo”


import tkinter as tk
from tkinter import *
from tkinter import ttk

LARGE_FONT=("Verdana", 12)

class Movies(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self,*args, **kwargs)

        tk.Tk.wm_title(self, "Movie I like")
        tk.Tk.wm_geometry(self, "500x500")
        container=tk.Frame(self)
        container.pack(side="top", fill="both", expand="True")
        
        self.app_data = {"movie":    StringVar(),
                         "popcorn": StringVar(),
                         "monday": BooleanVar(),
                         "tuesday": BooleanVar(),
                         "wednesday": BooleanVar(),
                         "thursday": BooleanVar(),
                         "friday": BooleanVar(),
                         "saturday": BooleanVar(),
                         "sunday": BooleanVar(),
                        }
        self.frames={}

        for F in (StartPage, PageOne, PageTwo):

            frame= F(container, self)
            self.frames[F]= frame

            frame.grid(row=0, column=0, sticky="nsew")


        self.show_frame(StartPage)
    
    def show_frame(self, cont):
        frame=self.frames[cont]
        frame.tkraise()



class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        tk.Frame.__init__(self, parent)

        s = ttk.Style()
        s.configure('my.TButton', font=('Verdana', 8))

        label=tk.Label(self, text="Home Page", font=LARGE_FONT)
        label.pack(pady=10, padx=30)

        label1=tk.Label(self, text="When are you available?")
        label1.pack()
        #CheckButton
        ttk.Checkbutton(self, text='Monday', variable=self.controller.app_data["monday"]).pack()
        ttk.Checkbutton(self, text='Tuesday', variable=self.controller.app_data["tuesday"]).pack()
        ttk.Checkbutton(self, text='Wednesday', variable=self.controller.app_data["wednesday"]).pack()
        ttk.Checkbutton(self, text='Thursday', variable=self.controller.app_data["thursday"]).pack()
        ttk.Checkbutton(self, text='Friday', variable=self.controller.app_data["friday"]).pack()
        ttk.Checkbutton(self, text='Saturday', variable=self.controller.app_data["saturday"]).pack()
        ttk.Checkbutton(self, text='Sunday', variable=self.controller.app_data["sunday"]).pack()

        button_load=ttk.Button(self, text="Kind of Movie ", width=30, style='my.TButton',
                          command= lambda: controller.show_frame(PageOne))
        button_load.pack(padx=30)

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        tk.Frame.__init__(self, parent)

        mybutton=ttk.Radiobutton(self, text='Drama', variable=self.controller.app_data["movie"], value="Drama").grid(column=1,row=1, sticky=W, padx=10)
        mybutton1=ttk.Radiobutton(self, text='Comedy', variable=self.controller.app_data["movie"], value="Comedy").grid(column=2,row=1, sticky=W, padx=10)
        
        globals()['user_message_entry'] = tk.Text(self, height=10, width=60).grid(column=1, row= 3, padx=5)



        button_next=ttk.Button(self, text="Next >> ", width=30, style='my.TButton',
                          command= lambda: controller.show_frame(PageTwo)).grid(column=3, row= 10, padx=5)
        
class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        self.controller = controller
        tk.Frame.__init__(self, parent)
        
        body = globals()['user_message_entry'].get("1.0", "end")
        mybutton2=ttk.Radiobutton(self, text='Salty', variable=self.controller.app_data["popcorn"], value="Salty").grid(column=1,row=1, sticky=W, padx=10)
        mybutton3=ttk.Radiobutton(self, text='Sweet', variable=self.controller.app_data["popcorn"], value="Sweet").grid(column=2,row=1, sticky=W, padx=10)
        
        def save_info():
            pop_info=self.controller.app_data["popcorn"].get()
            movie_info=self.controller.app_data["movie"].get()
            week=["monday", "tuesday", "wednesday","thursday","friday","saturday","sunday"]
            print("you like " + movie_info + " and you would like " + pop_info +" popcorn")
            print("This is the body" + body)
            test=len(week)
            for i in range (0, test):
                if self.controller.app_data[week[i]].get() == True:
                    print(week[i])


        button_submit=ttk.Button(self, text="Submit", width=15,
                          command=save_info).grid(column=3, row= 10, padx=5)


app=Movies()
app.mainloop()

一种解决方案是像保存其他内容一样将小部件存储在控制器中。

例如:

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        ...
        self.controller.app_data["user_message_entry"] = Text(self, height=10, width=60)
        ...

然后,要获取值,它类似于获取其他变量的方式:

body = self.controller.app_data['user_message_entry'].get("1.0", "end")

另一种访问它的方法是为您的控制器提供一个功能,该功能将 return 一个页面。然后,您可以使用 returned 页面访问它。

例如,首先在控制器中添加一个函数到return一个页面:

class Movies(tk.Tk):
    ...
    def get_page(self, page_class):
        return self.frames[page_class]
    ...

接下来,确保文本小部件是一个实例变量:

class PageOne(tk.Frame):
    def __init__(self, parent, controller):
        ...
        self.user_message_entry' = tk.Text(self, height=10, width=60).grid(column=1, row= 3, padx=5)
        ...

最后,在控制器中使用该函数获取另一个页面,然后从那里获取文本小部件:

page = self.controller.get_page(PageOne)
body = page.textuser_message_entry.get("1.0", "end")

上面介绍了如何从多个地方访问文本小部件。但是,您还有另一个问题,因为您编写的代码试图在创建小部件几毫秒后从小部件中获取文本。您需要等到用户有机会在获取数据之前输入小部件。

例如,您需要将 body = page.textuser_message_entry.get("1.0", "end") 移动到 save_info 函数内部。