在 Python3/tkinter 中,是否可以将工具栏创建到单独的 class 中,但仍允许它与主应用程序交互?
in Python3/tkinter is it possible to create a toolbar into a separate class, but still allowing it to interact with the main app?
我即将开始一个新的 Python3/tkinter 项目,我想确保尽可能多地编写代码。我正在创建一个应用程序,目前,一个 window 由 3 个区域组成:
- 工具栏
- Center/main 面积
- 状态栏
我正在努力保持主应用程序 class 尽可能干净,将代码卸载到其他辅助 classes。因此,按照一些教程并根据我到目前为止所做的事情进行调整,我已经能够从主应用程序设置一个可以按需更改的外部工具栏 class。现在,我正在尝试为工具栏创建一个 class,但恐怕无法在单独的 class 中创建按钮及其各自的回调,因为我不知道如何让他们调用主应用程序中的功能。这可能吗?
这是我现在得到的:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
class App:
""" main class for the application """
def __init__(self,master):
mainframe = ttk.Frame(master)
topframe = ttk.Frame(mainframe)
centerframe = ttk.Frame(mainframe)
bottomframe = ttk.Frame(mainframe)
my_toolbar = Toolbar(topframe)
my_statusbar = StatusBar(mainframe)
my_statusbar.set("This is the statusbar")
centerlabel = ttk.Label(centerframe, text="Center stuff goes here")
centerlabel.pack()
topframe.pack(side=TOP, fill=X)
centerframe.pack(side=TOP, fill=BOTH)
bottomframe.pack(side=BOTTOM, fill=X)
mainframe.pack(side=TOP, expand=True, fill=BOTH)
def button_function(self, *event):
print("filter")
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.label = ttk.Label(self,anchor=W)
self.label.pack()
self.pack(side=BOTTOM, fill=X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar:
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
def __init__(self,master):
self.button1 = ttk.Button(master,text="One",command=self.button_one())
self.button2 = ttk.Button(master,text="Two",command=self.button_two())
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = Tk()
app = App(root)
root.mainloop()
假设我需要让 button1
触发 button_function()
以更新那里显示的一些信息。我是否应该简单地将工具栏移动到 App
class 中,例如在从其 __init__()
调用的 class 方法中?或者有更好的方法吗?
也许我应该补充一点,我打算稍后添加一些 Toplevel
windows,它们可能会利用其中的一些通用 classes。我想好好铺路
这当然是可能的。这里有两种可能性。第一个让应用程序继承自 ttk.Frame 而不是使用大型机。然后你可以将 App 作为 master 传递给工具栏等。这是重做的代码:
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
class App(ttk.Frame):
""" main class for the application """
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.my_toolbar = Toolbar(self)
self.my_statusbar = StatusBar(self)
self.my_statusbar.set("This is the statusbar")
self.centerframe = CenterFrame(self)
self.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def button_function(self, *event):
print("filter")
class CenterFrame(ttk.Frame):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.pack(side=tk.BOTTOM, fill=tk.X)
self.centerlabel = ttk.Label(self, text="Center stuff goes here")
self.centerlabel.pack()
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.master = master
self.label = ttk.Label(self,anchor=tk.W)
self.label.pack()
self.pack(side=tk.BOTTOM, fill=tk.X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar(ttk.Frame):
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
self.master.button_function()
def __init__(self,master):
super().__init__(master)
self.master = master
self.pack(side=tk.TOP, fill=tk.X)
self.button1 = ttk.Button(self,text="One",command=self.button_one)
self.button2 = ttk.Button(self,text="Two",command=self.button_two)
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()
第二个是将 App 作为参数传递给另一个 类。
您遗漏了一些 self.
,按钮命令分配不需要括号,之后您可以从程序中的任何位置调用按钮配置。所以对于 button1 命令,这将是:
app.my_toolbar.button1.config(command=app.button_function)
我正在按原样修复您的错误,而不是让程序变得更好:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
class App:
""" main class for the application """
def __init__(self,master):
self.mainframe = ttk.Frame(master)
self.topframe = ttk.Frame(self.mainframe)
self.centerframe = ttk.Frame(self.mainframe)
self.bottomframe = ttk.Frame(self.mainframe)
self.my_toolbar = Toolbar(self.topframe)
self.my_statusbar = StatusBar(self.mainframe)
self.my_statusbar.set("This is the statusbar")
self.centerlabel = ttk.Label(self.centerframe, text="Center stuff goes here")
self.centerlabel.pack()
self.topframe.pack(side=TOP, fill=X)
self.centerframe.pack(side=TOP, fill=BOTH)
self.bottomframe.pack(side=BOTTOM, fill=X)
self.mainframe.pack(side=TOP, expand=True, fill=BOTH)
def button_function(self, *event):
print("filter")
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.label = ttk.Label(self,anchor=W)
self.label.pack()
self.pack(side=BOTTOM, fill=X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar:
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
def __init__(self,master):
self.button1 = ttk.Button(master,text="One",command=self.button_one)
self.button2 = ttk.Button(master,text="Two",command=self.button_two)
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = Tk()
app = App(root)
app.my_toolbar.button1.config(command=app.button_function)
root.mainloop()
我即将开始一个新的 Python3/tkinter 项目,我想确保尽可能多地编写代码。我正在创建一个应用程序,目前,一个 window 由 3 个区域组成:
- 工具栏
- Center/main 面积
- 状态栏
我正在努力保持主应用程序 class 尽可能干净,将代码卸载到其他辅助 classes。因此,按照一些教程并根据我到目前为止所做的事情进行调整,我已经能够从主应用程序设置一个可以按需更改的外部工具栏 class。现在,我正在尝试为工具栏创建一个 class,但恐怕无法在单独的 class 中创建按钮及其各自的回调,因为我不知道如何让他们调用主应用程序中的功能。这可能吗?
这是我现在得到的:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
class App:
""" main class for the application """
def __init__(self,master):
mainframe = ttk.Frame(master)
topframe = ttk.Frame(mainframe)
centerframe = ttk.Frame(mainframe)
bottomframe = ttk.Frame(mainframe)
my_toolbar = Toolbar(topframe)
my_statusbar = StatusBar(mainframe)
my_statusbar.set("This is the statusbar")
centerlabel = ttk.Label(centerframe, text="Center stuff goes here")
centerlabel.pack()
topframe.pack(side=TOP, fill=X)
centerframe.pack(side=TOP, fill=BOTH)
bottomframe.pack(side=BOTTOM, fill=X)
mainframe.pack(side=TOP, expand=True, fill=BOTH)
def button_function(self, *event):
print("filter")
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.label = ttk.Label(self,anchor=W)
self.label.pack()
self.pack(side=BOTTOM, fill=X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar:
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
def __init__(self,master):
self.button1 = ttk.Button(master,text="One",command=self.button_one())
self.button2 = ttk.Button(master,text="Two",command=self.button_two())
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = Tk()
app = App(root)
root.mainloop()
假设我需要让 button1
触发 button_function()
以更新那里显示的一些信息。我是否应该简单地将工具栏移动到 App
class 中,例如在从其 __init__()
调用的 class 方法中?或者有更好的方法吗?
也许我应该补充一点,我打算稍后添加一些 Toplevel
windows,它们可能会利用其中的一些通用 classes。我想好好铺路
这当然是可能的。这里有两种可能性。第一个让应用程序继承自 ttk.Frame 而不是使用大型机。然后你可以将 App 作为 master 传递给工具栏等。这是重做的代码:
#!/usr/bin/python3
import tkinter as tk
from tkinter import ttk
class App(ttk.Frame):
""" main class for the application """
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.my_toolbar = Toolbar(self)
self.my_statusbar = StatusBar(self)
self.my_statusbar.set("This is the statusbar")
self.centerframe = CenterFrame(self)
self.pack(side=tk.TOP, expand=True, fill=tk.BOTH)
def button_function(self, *event):
print("filter")
class CenterFrame(ttk.Frame):
def __init__(self,master,*args,**kwargs):
super().__init__(master,*args,**kwargs)
self.master = master
self.pack(side=tk.BOTTOM, fill=tk.X)
self.centerlabel = ttk.Label(self, text="Center stuff goes here")
self.centerlabel.pack()
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.master = master
self.label = ttk.Label(self,anchor=tk.W)
self.label.pack()
self.pack(side=tk.BOTTOM, fill=tk.X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar(ttk.Frame):
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
self.master.button_function()
def __init__(self,master):
super().__init__(master)
self.master = master
self.pack(side=tk.TOP, fill=tk.X)
self.button1 = ttk.Button(self,text="One",command=self.button_one)
self.button2 = ttk.Button(self,text="Two",command=self.button_two)
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()
第二个是将 App 作为参数传递给另一个 类。
您遗漏了一些 self.
,按钮命令分配不需要括号,之后您可以从程序中的任何位置调用按钮配置。所以对于 button1 命令,这将是:
app.my_toolbar.button1.config(command=app.button_function)
我正在按原样修复您的错误,而不是让程序变得更好:
#!/usr/bin/python3
from tkinter import *
from tkinter import ttk
class App:
""" main class for the application """
def __init__(self,master):
self.mainframe = ttk.Frame(master)
self.topframe = ttk.Frame(self.mainframe)
self.centerframe = ttk.Frame(self.mainframe)
self.bottomframe = ttk.Frame(self.mainframe)
self.my_toolbar = Toolbar(self.topframe)
self.my_statusbar = StatusBar(self.mainframe)
self.my_statusbar.set("This is the statusbar")
self.centerlabel = ttk.Label(self.centerframe, text="Center stuff goes here")
self.centerlabel.pack()
self.topframe.pack(side=TOP, fill=X)
self.centerframe.pack(side=TOP, fill=BOTH)
self.bottomframe.pack(side=BOTTOM, fill=X)
self.mainframe.pack(side=TOP, expand=True, fill=BOTH)
def button_function(self, *event):
print("filter")
class StatusBar(ttk.Frame):
""" Simple Status Bar class - based on Frame """
def __init__(self,master):
ttk.Frame.__init__(self,master)
self.label = ttk.Label(self,anchor=W)
self.label.pack()
self.pack(side=BOTTOM, fill=X)
def set(self,texto):
self.label.config(text=texto)
self.label.update_idletasks()
def clear(self):
self.label.config(text="")
self.label.update_idletasks()
class Toolbar:
""" Toolbar """
def button_one(self):
print("button 1 pressed")
def button_two(self):
print("button 2 pressed")
def __init__(self,master):
self.button1 = ttk.Button(master,text="One",command=self.button_one)
self.button2 = ttk.Button(master,text="Two",command=self.button_two)
self.button1.grid(row=0,column=0)
self.button2.grid(row=0,column=1)
if __name__ == "__main__":
root = Tk()
app = App(root)
app.my_toolbar.button1.config(command=app.button_function)
root.mainloop()