Python 3.x Python和Tkinter:如何从不同的类设置StringVar

Python 3.x Python和Tkinter:如何从不同的类设置StringVar,python-3.x,tkinter,Python 3.x,Tkinter,我正在学习一些python和tkinter,并尝试了一个非常简单的示例应用程序 tkinter GUI、显示文本的标签和下面的两个按钮。 这些按钮用于更改标签中的文本,因为它通过textvariable参数链接到StringVar 应该发生什么,简单地说: 按下一个按钮,标签上将显示一个 按B按钮,标签上将显示B 但是,当我按下按钮A时,程序会给我一个名称错误:名称“display\u frame”未定义 我想不出发生了什么事。我正在访问对象属性 obs:由于按钮A有问题,未尝试为按钮B配置功能

我正在学习一些python和tkinter,并尝试了一个非常简单的示例应用程序

tkinter GUI、显示文本的标签和下面的两个按钮。 这些按钮用于更改标签中的文本,因为它通过textvariable参数链接到StringVar

应该发生什么,简单地说: 按下一个按钮,标签上将显示一个 按B按钮,标签上将显示B

但是,当我按下按钮A时,程序会给我一个名称错误:名称“display\u frame”未定义

我想不出发生了什么事。我正在访问对象属性

obs:由于按钮A有问题,未尝试为按钮B配置功能

进口tkinter TkinterWindowtkinter.Tk类: 定义初始自我: 超级__ self.rowconfigure0,权重=1 self.columnconfigure0,权重=1 self.configurebackground='orange' 类DisplayFrametkinter.Frame: 定义初始自我,父级: 超级。初始父级 self.rowconfigure0,权重=1 self.columnconfigure0,权重=1 self.configurebackground='cyan' self.gridrow=0,column=0,pady=5,padx=5,sticky='nsew' self.text=tkinter.StringVar self.text.set'Hello' self.display=tkinter.Labelself,textvariable=self.text,font=15,bg=bebebe,relief=groove,bd=5,height=5 self.display.gridsticky='nsew' 类按钮框架。框架: 定义初始自我,父级: 超级。初始父级 self.rowconfigure0,权重=1 self.columnconfigure0,权重=1 self.column配置1,权重=1 self.configurebackground='green' self.gridrow=1,column=0,pady=5,padx=5,sticky='nsew' self.button\u A=tkinter.Buttonself,text='A',command=self.write\u A self.button_A.gridrow=0,column=0,padx=15,sticky='nsew' self.button_B=tkinter.Buttonself,text='B' self.button_B.gridrow=0,column=1,padx=15,sticky='nsew' def写入自身: 显示框架文本。设置“A” def主: window=TkinterWindow display\u frame=DisplayFramewindow 按钮\框架=按钮框架窗口 window.mainloop 主要的
您面临的主要问题是类属性self.text对其他类不可见。解决这个问题的一种方法是将该变量移动到主tk类,然后直接引用它。这是对代码的最快修复

import tkinter

class TkinterWindow(tkinter.Tk):
    def __init__(self):
        super().__init__()
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.configure(background='orange')
        self.text = tkinter.StringVar()
        self.text.set('Hello')


class DisplayFrame(tkinter.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.configure(background='cyan')
        self.grid(row=0, column=0, pady=5, padx=5, sticky='nsew')


        self.display = tkinter.Label(self, textvariable=self.master.text, font=15, bg="#bebebe", relief="groove", bd=5, height=5 )
        self.display.grid(sticky='nsew')

class ButtonsFrame(tkinter.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.columnconfigure(1, weight=1)
        self.configure(background='green')
        self.grid(row=1, column=0, pady=5, padx=5, sticky='nsew')

        self.button_A = tkinter.Button(self, text='A', command=self.write_A)
        self.button_A.grid(row=0, column=0, padx=15, sticky='nsew')

        self.button_B = tkinter.Button(self, text='B')
        self.button_B.grid(row=0, column=1, padx=15, sticky='nsew')

    def write_A(self):
        self.master.text.set('A')


def main():
    window = TkinterWindow()
    display_frame = DisplayFrame(window)
    buttons_frame = ButtonsFrame(window)
    window.mainloop()

main()
也就是说,您的代码中有一些东西需要注意。过度使用自我。当不需要时,在frame类中应用几何体管理也是一个坏主意


就我个人而言,我会在一个类中构建这一切

import tkinter as tk


class TkinterWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.rowconfigure(0, weight=1)
        self.columnconfigure(0, weight=1)
        self.configure(background='orange')

        self.text = tk.StringVar()
        self.text.set('Hello')

        display_frame = tk.Frame(self, background='cyan')
        ButtonsFrame = tk.Frame(self, background='green')
        display_frame.rowconfigure(0, weight=1)
        display_frame.columnconfigure(0, weight=1)
        ButtonsFrame.rowconfigure(0, weight=1)
        ButtonsFrame.columnconfigure(0, weight=1)
        ButtonsFrame.columnconfigure(1, weight=1)

        display_frame.grid(row=0, column=0, pady=5, padx=5, sticky='nsew')
        ButtonsFrame.grid(row=1, column=0, pady=5, padx=5, sticky='nsew')

        tk.Label(display_frame, textvariable=self.text, font=15,
                 bg="#bebebe", relief="groove", bd=5).grid(row=0, column=0, sticky='nsew')

        tk.Button(ButtonsFrame, text='A',
                  command=lambda: self.update_text('A')).grid(row=0, column=0, padx=15, sticky='nsew')
        tk.Button(ButtonsFrame, text='B',
                  command=lambda: self.update_text('B')).grid(row=0, column=1, padx=15, sticky='nsew')

    def update_text(self, value):
        self.text.set(value)

TkinterWindow().mainloop()

如果您将显示框全球化,那么它将起作用,但这不是推荐的方法。正确的方法是在DisplayFrame和ButtonsFrame之间建立连接,以访问彼此的属性。>您遇到的主要问题是类属性self.text对其他类不可见。我对此有点困惑。。。我不是通过对象访问self.text吗?>在frame类中应用几何体管理也是个坏主意。好的,关于这一点有什么不对的地方以及在哪里应用网格管理代码?@BrunoLemos在您的示例display_框架中不在全局名称空间中,只在main函数的本地名称空间中。由于这个原因,当方法write_A尝试查找display_帧时,它首先在write_A中查找本地,因为它没有在那里找到它,所以它会检查全局,也没有在那里找到它。实际上,您可以通过将main中的代码移动到全局名称空间来测试这一点,它应该在全局名称空间中工作。@BrunoLemos关于几何问题,以这个例子为例。如果我决定在某些东西上使用pack,然后尝试使用frame类,则会导致代码出错。在这个特殊的例子中,它现在并没有伤害到你,但是它的坏习惯很可能会给你带来错误。会在一个类中构建这一切。我的想法是让它可读。。。容易找到和组织的东西。。。不是吗?大多数代码和程序都是一个很好的单例文件吗?而我对花哨的组织有一个错误的概念吗?