如何使用 tkinter 从另一个 class 中修改一个 class 中使用的变量?
How can I modify a variable being used in one class from another class by using tkinter?
我想要完成的是一种在另一个 class 实例中更改变量的方法。我一直在摸不着头脑,试图了解这是如何(或是否)可能的。
How can one update the value of self.lblvar
that is in the class
MainWindow
from the class SecondWindow
?
这就是我用来检验我的理论的工作:
from tkinter import *
class MainWindow:
def __init__(self, rootWin):
self.rootWin = rootWin
self.rootWin.geometry('400x200')
self.mainMenu = Menu(self.rootWin)
self.mainMenu.add_command(label = 'Open Second Window', command = self.openSecondWindow)
self.lblvar = StringVar()
self.lblvar.set('Change Me!')
self.lbl = Label(rootWin, textvariable = self.lblvar)
self.lbl.pack()
self.rootWin.config(menu = self.mainMenu)
def openSecondWindow(self):
self.secondWin = Tk()
self.secWin = SecondWindow(self)
self.secondWin.mainloop()
class SecondWindow:
def __init__(self, parent):
self.parent = parent
self.btn = Button(self, label = 'Change Label?', command = self.changeOther)
self.btn.pack()
def changeOther(self):
self.parent.lblvar.set('Changed it!')
def main():
root = Tk()
mainWin = MainWindow(root)
root.mainloop()
if __name__ == "__main__":
main()
我在 Python classes 方面有点新手,所以任何关于此的指导 and/or 解释将不胜感激!
编辑:将原始问题更改为更清晰的问题以帮助进一步搜索该主题
是的。完全有可能从另一个 class 中修改 class 的状态或 class 的实例。与 C++ 等传统 OOP 语言不同,Python 不强制执行任何访问规则 - 一切都是 public.
class ClassA:
def __init__(self, var_a):
self.var_a = var_a
def change_var_c(self, instance_b, new_value):
instance_b.var_c = new_value
def change_var_b(self, new_value):
ClassB.VAR_B = new_value
class ClassB:
VAR_B = 2
def __init__(self, var_c):
self.var_c = var_c
instance_a = ClassA(1)
instance_b = ClassB(3)
instance_a.change_var_c(instance_b, 4)
print(instance_b.var_c) # prints 4
instance_a.change_var_b(5)
print(ClassB.VAR_B) # prints 5
尽管如此,这可能不是您应该做的事情。修改对象的内部结构违反了封装原则。 类 应该公开一个 public 接口来修改它们的 "private" 成员。
因此,让您的代码按预期工作所需的最小更改是更改您的 class SecondWindow
以接受 2 个参数,一个用于顶层 window一个用于主要 window class 以及更改方法 openSecondWindow
以使用 Toplevel
window 而不是 [=15= 的第二个实例] 因为你不应该在 tkinter GUI 中使用多个 Tk()
实例。一个小问题是您在按钮内部使用了 label =
,而这实际上应该是 text=
。所以我们可以使用 class 属性。
像这样:
def openSecondWindow(self):
self.secondWin = Toplevel(self.rootWin)
self.secWin = SecondWindow(self.secondWin, self)
class SecondWindow:
def __init__(self, top, master):
self.master = master
self.btn = Button(top, text='Change Label?', command=self.changeOther)
self.btn.pack()
def changeOther(self):
self.master.lblvar.set('Changed it!')
也就是说,我会整体更改一些内容以提高可读性并减少代码行数。
import tkinter as tk
而不是使用 *
。这将有助于防止覆盖内置 methods/other 导入,并清楚说明您在代码中使用的是哪个库。
从 class 中的 Tk()
和 Toplevel()
继承,使事情更容易使用。
只在需要的地方使用self.
。您代码中的某些地方不需要这样做。
请参阅下面修改后的示例,如果您有任何问题,请告诉我:
import tkinter as tk
class MainWindow(tk.Tk):
def __init__(self):
# super is used to avoid referring to the base class explicitly.
# to read more on this check out the link below.
super().__init__()
self.geometry('400x200')
main_menu = tk.Menu(self)
self.config(menu=main_menu)
main_menu.add_command(label='Open Second Window', command=SecondWindow)
self.lblvar = tk.StringVar(value='Change Me!')
# No need to use `self.` on this label as we are working with the lblvar in the 2nd window and not the label.
tk.Label(self, textvariable=self.lblvar).pack()
class SecondWindow(tk.Toplevel):
def __init__(self):
super().__init__()
# No need to use `self.` on this button unless down the road you want to change this button in some way.
tk.Button(self, text='Change Label?', command=self.change_other).pack()
def change_other(self):
# with inheriting like this in tkinter you do not need to define self.master as it is automatic here.
# Other classes or methods may need it defined however. Just wanted to make sure you are aware of this.
self.master.lblvar.set('Changed it!')
if __name__ == "__main__":
MainWindow().mainloop()
结果:
有关 super()
的更多详细信息。
我想要完成的是一种在另一个 class 实例中更改变量的方法。我一直在摸不着头脑,试图了解这是如何(或是否)可能的。
How can one update the value of
self.lblvar
that is in the classMainWindow
from the classSecondWindow
?
这就是我用来检验我的理论的工作:
from tkinter import *
class MainWindow:
def __init__(self, rootWin):
self.rootWin = rootWin
self.rootWin.geometry('400x200')
self.mainMenu = Menu(self.rootWin)
self.mainMenu.add_command(label = 'Open Second Window', command = self.openSecondWindow)
self.lblvar = StringVar()
self.lblvar.set('Change Me!')
self.lbl = Label(rootWin, textvariable = self.lblvar)
self.lbl.pack()
self.rootWin.config(menu = self.mainMenu)
def openSecondWindow(self):
self.secondWin = Tk()
self.secWin = SecondWindow(self)
self.secondWin.mainloop()
class SecondWindow:
def __init__(self, parent):
self.parent = parent
self.btn = Button(self, label = 'Change Label?', command = self.changeOther)
self.btn.pack()
def changeOther(self):
self.parent.lblvar.set('Changed it!')
def main():
root = Tk()
mainWin = MainWindow(root)
root.mainloop()
if __name__ == "__main__":
main()
我在 Python classes 方面有点新手,所以任何关于此的指导 and/or 解释将不胜感激!
编辑:将原始问题更改为更清晰的问题以帮助进一步搜索该主题
是的。完全有可能从另一个 class 中修改 class 的状态或 class 的实例。与 C++ 等传统 OOP 语言不同,Python 不强制执行任何访问规则 - 一切都是 public.
class ClassA:
def __init__(self, var_a):
self.var_a = var_a
def change_var_c(self, instance_b, new_value):
instance_b.var_c = new_value
def change_var_b(self, new_value):
ClassB.VAR_B = new_value
class ClassB:
VAR_B = 2
def __init__(self, var_c):
self.var_c = var_c
instance_a = ClassA(1)
instance_b = ClassB(3)
instance_a.change_var_c(instance_b, 4)
print(instance_b.var_c) # prints 4
instance_a.change_var_b(5)
print(ClassB.VAR_B) # prints 5
尽管如此,这可能不是您应该做的事情。修改对象的内部结构违反了封装原则。 类 应该公开一个 public 接口来修改它们的 "private" 成员。
因此,让您的代码按预期工作所需的最小更改是更改您的 class SecondWindow
以接受 2 个参数,一个用于顶层 window一个用于主要 window class 以及更改方法 openSecondWindow
以使用 Toplevel
window 而不是 [=15= 的第二个实例] 因为你不应该在 tkinter GUI 中使用多个 Tk()
实例。一个小问题是您在按钮内部使用了 label =
,而这实际上应该是 text=
。所以我们可以使用 class 属性。
像这样:
def openSecondWindow(self):
self.secondWin = Toplevel(self.rootWin)
self.secWin = SecondWindow(self.secondWin, self)
class SecondWindow:
def __init__(self, top, master):
self.master = master
self.btn = Button(top, text='Change Label?', command=self.changeOther)
self.btn.pack()
def changeOther(self):
self.master.lblvar.set('Changed it!')
也就是说,我会整体更改一些内容以提高可读性并减少代码行数。
import tkinter as tk
而不是使用*
。这将有助于防止覆盖内置 methods/other 导入,并清楚说明您在代码中使用的是哪个库。从 class 中的
Tk()
和Toplevel()
继承,使事情更容易使用。只在需要的地方使用
self.
。您代码中的某些地方不需要这样做。
请参阅下面修改后的示例,如果您有任何问题,请告诉我:
import tkinter as tk
class MainWindow(tk.Tk):
def __init__(self):
# super is used to avoid referring to the base class explicitly.
# to read more on this check out the link below.
super().__init__()
self.geometry('400x200')
main_menu = tk.Menu(self)
self.config(menu=main_menu)
main_menu.add_command(label='Open Second Window', command=SecondWindow)
self.lblvar = tk.StringVar(value='Change Me!')
# No need to use `self.` on this label as we are working with the lblvar in the 2nd window and not the label.
tk.Label(self, textvariable=self.lblvar).pack()
class SecondWindow(tk.Toplevel):
def __init__(self):
super().__init__()
# No need to use `self.` on this button unless down the road you want to change this button in some way.
tk.Button(self, text='Change Label?', command=self.change_other).pack()
def change_other(self):
# with inheriting like this in tkinter you do not need to define self.master as it is automatic here.
# Other classes or methods may need it defined however. Just wanted to make sure you are aware of this.
self.master.lblvar.set('Changed it!')
if __name__ == "__main__":
MainWindow().mainloop()
结果:
有关 super()
的更多详细信息。