【问题标题】:How to properly access a StringVar() of a class from another class - Python - tkinter [duplicate]如何从另一个类中正确访问一个类的 StringVar() - Python - tkinter [重复]
【发布时间】:2018-11-05 01:58:31
【问题描述】:

(我正在使用 mac 10.8.5 和 Python3 与 PyCharm)

我有一个 tkinter GUI TestMain() 类加上一个 PageOne() 类和一个 PageTwo() 类。 我需要 PageOne()PageTwo() 成为不同的 GUI 窗口,因为它们将处理不同的数据。 我最小化了代码以使其尽可能可读。 经过多次测试,我尝试将tk.StringVar() 和一个简单的函数放在全局范围内,如下所示,但仍然存在问题。

import tkinter as tk

page1_label = tk.StringVar()
page2_entry = tk.StringVar()

def set_ebdata():
    data = page2_entry.get()
    page1_label.set(data)


class TestMain(tk.Tk):

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

        tk.Tk.wm_title(self, 'TEST GUI')
        container = tk.Frame(self)
        container.pack(side='top')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.configure(background='lightgrey')
            frame.grid(row=0, column=0, sticky='nswe')
        self.show_frame(PageOne)

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


class PageOne(tk.Frame):

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

        frame_eb_data = tk.Frame(self, width=100, height=100, bg="orange", colormap="new")
        frame_eb_data.grid(row=0, column=0, sticky='w', padx=5, pady=5)
        frame_but_right = tk.Frame(self, width=240, height=60, bg="yellow", colormap="new")
        frame_but_right.grid(row=0, column=1, padx=5, pady=5, rowspan=2)
        lab_eb_data = tk.Label(frame_eb_data, background='#DDD4EF', textvariable=page1_label)
        lab_eb_data.grid(row=0, column=0, sticky='n')

        b_ebdata = tk.Button(frame_but_right, text="Page 2", width=10, height=2, command=lambda: controller.show_frame(PageTwo))
        b_ebdata.grid(row=3, column=0)


class PageTwo(tk.Frame):

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

        frame_buttons = tk.Frame(self, width=455, bg="#DDD4EF", colormap="new")
        frame_buttons.grid(row=0, column=0, padx=5, pady=5, sticky='e')
        frame_up_left = tk.Frame(self, width=485, height=260, bg="#89E3FA", colormap="new")
        frame_up_left.grid(row=1, column=0, sticky='w', padx=5, pady=5)

        b_data = tk.Label(frame_buttons, text='Example GUI', font='TrebuchetMS 30 bold', background="#DDD4EF")
        b_data.grid(row=0, column=0, padx=13, pady=5, sticky='w')

        b5 = tk.Button(frame_buttons, text='Set Text', command=lambda: set_ebdata)
        b5.grid(row=0, column=2, padx=5, pady=5, sticky='e')

        b6 = tk.Button(frame_buttons, text='Page 1', command=lambda: controller.show_frame(PageOne))
        b6.grid(row=0, column=3, padx=5, pady=5, sticky='e')

        label_2 = tk.Label(frame_up_left, text="Name:", font=("bold", 14))
        label_2.grid(row=1, column=0, sticky='e')
        entry_nombre_fld = tk.Entry(frame_up_left, width=40, textvariable=page2_entry)
        entry_nombre_fld.grid(row=1, column=1, columnspan=3, sticky='w')


app = TestMain()

app.mainloop()

当您运行程序时,会出现一个带有“Page 2”按钮 (b_ebdata) 的窗口,单击它会进入带有“Set Text”按钮 (b5) 的 Page 2 窗口,“Page 1” " 按钮 (b6) 和一个输入字段 (entry_nombre_fld)。

我想通过点击“设置文本”按钮 (b5) 来设置我将在第 1 页标签 (lab_eb_data) 的输入字段 (entry_nombre_fld) 中输入的文本。

解决方案是否可以将page1_label = tk.StringVar() 放入PageOne() 类,将page2_entry = tk.StringVar() 放入PageTwo() 类并使它们可以相互访问?

还有什么建议吗?

提前感谢您的帮助!

【问题讨论】:

  • 如果在类中始终使用self 引用该变量,则class.variableName 可以从脚本中的任何位置访问类变量。
  • 您正尝试在 Tk() 实例之前创建变量。在启动 Tk() 之前,您无法创建 tk 对象。
  • 将你的StringVar()'s 作为类属性移动到主类中,然后在其他类中使用控制器参数引用它们。像这样:textvariable=controller.page1_label

标签: python python-3.x tkinter


【解决方案1】:

我不得不更改一些东西,但大多数情况下主要的解决方案是将您的StringVar() 移动到主类中。然后接下来我们可以使用其他 2 个类中的controller 参数来操作数据。

我在第 2 页添加了一个函数来处理更新标签 StringVar。 因此,我删除了您为此拥有的其他功能。

我不得不将您的输入字段更改为类属性,以便我们可以在新方法中使用它的内容。我还必须在第 2 页中为 controller 创建一个类属性,以便我们也可以在方法中使用控制器。

现在可能有一个更简单的方法,但这是我用你的代码管理的。

import tkinter as tk


class TestMain(tk.Tk):

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

        self.title('TEST GUI')
        # Moved StringVar()'s to the main class
        self.page1_label = tk.StringVar()
        self.page2_entry = tk.StringVar()
        container = tk.Frame(self)
        container.pack(side='top')
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (PageOne, PageTwo):
            frame = F(container, self)
            self.frames[F] = frame
            frame.configure(background='lightgrey')
            frame.grid(row=0, column=0, sticky='nswe')
        self.show_frame(PageOne)

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

   # Deleted this function


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

        frame_eb_data = tk.Frame(self, width=100, height=100, bg="orange")
        frame_eb_data.grid(row=0, column=0, sticky='nsew', padx=5, pady=5)
        frame_but_right = tk.Frame(self, width=240, height=60, bg="yellow")
        frame_but_right.grid(row=1, column=0, padx=5, pady=5, sticky='nsew')
        lab_eb_data = tk.Label(frame_eb_data, background='#DDD4EF', textvariable=controller.page1_label)
        lab_eb_data.grid(row=0, column=0)

        b_ebdata = tk.Button(frame_but_right, text="Page 2", width=10, height=2, command=lambda: controller.show_frame(PageTwo))
        b_ebdata.grid(row=0, column=0)


class PageTwo(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        # Added the self.controller so the method below can use it.
        self.controller = controller
        frame_buttons = tk.Frame(self, width=455, bg="#DDD4EF", colormap="new")
        frame_buttons.grid(row=0, column=0, padx=5, pady=5, sticky='e')
        frame_up_left = tk.Frame(self, width=485, height=260, bg="#89E3FA", colormap="new")
        frame_up_left.grid(row=1, column=0, sticky='w', padx=5, pady=5)

        b_data = tk.Label(frame_buttons, text='Example GUI', font='TrebuchetMS 30 bold', background="#DDD4EF")
        b_data.grid(row=0, column=0, padx=13, pady=5, sticky='w')
        b5 = tk.Button(frame_buttons, text='Set Text', command= self.update_p2_label)
        b5.grid(row=0, column=2, padx=5, pady=5, sticky='e')
        b6 = tk.Button(frame_buttons, text='Page 1', command=lambda: controller.show_frame(PageOne))
        b6.grid(row=0, column=3, padx=5, pady=5, sticky='e')

        self.entry_nombre_fld = tk.Entry(frame_up_left, width=40)
        self.entry_nombre_fld.grid(row=1, column=1, columnspan=3, sticky='w')
        label_2 = tk.Label(frame_up_left, text="Name:", font=("bold", 14))
        label_2.grid(row=1, column=0, sticky='e')
    # Added this function to update the page1_label StringVar.
    def update_p2_label(self):
        self.controller.page1_label.set(self.entry_nombre_fld.get())


app = TestMain()
app.mainloop()

【讨论】:

  • 它确实奏效了!非常感谢!
猜你喜欢
  • 2019-04-03
  • 1970-01-01
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 2018-06-17
相关资源
最近更新 更多