我有一个包含多个框架的GUI,每个框架包含多个标签/输入字段。我正在尝试添加一个“设置”选项,该选项将允许用户更改所有框架和标签的背景颜色。到目前为止,我已经设法完成了该任务,但需要警告一个新的Tk窗口,该窗口将弹出并显示选定的背景,而不是在当前窗口上进行更新。
import tkinter as tk
from tkinter import ttk
from tkinter import colorchooser
bg_hex = '#f0f0f0f0f0f0' #default background color
def pick_color():
global bg_hex
bg_color = colorchooser.askcolor()
bg_hex = bg_color[1]
Master().update()
print(bg_hex)
class Master(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side='top', fill='both', expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (HomePage, PageOne, PageTwo, Settings):
frame = F(container, self)
self.frames[F] = frame
frame.config(bg = bg_hex)
frame.grid(row=0, column=0, sticky='nsew')
self.show_frame(HomePage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text='Home Page', font=('Verdana', 12), bg=bg_hex)
label.pack(pady=5)
button1 = tk.Button(self, text='Page One', command=lambda: controller.show_frame(PageOne))
button1.pack(pady=5, ipadx=2)
button2 = tk.Button(self, text='Page Two', command=lambda: controller.show_frame(PageTwo))
button2.pack(pady=5)
button3 = tk.Button(self, text='Settings', command=lambda: controller.show_frame(Settings))
button3.pack(side='bottom', pady=10)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Page One', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2, pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Page Two', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2,pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
class Settings(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Settings', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2,pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
button2 = tk.Button(self, text='Choose Background', command= pick_color)
button2.grid()
Master().mainloop()
运行代码块时不会发生错误,但是当您选择“选择背景”按钮并选择一种颜色时,将打开一个新的Tk窗口,并显示选定的背景颜色,而不是更新当前的Tk窗口。
**更新代码以不反映全局变量,以希望它可以帮助其他人。
我在每个Frame类下添加了self.controller = controller
,将pick_color
和color_update
合并为1个函数,并放置在Tk类下。
def pick_color_bg(self):
bg_color = colorchooser.askcolor()
bg_hex = bg_color[1]
# Loop through pages and contained widgets and set color
for cls, obj in self.frames.items():
obj.config(bg=bg_hex) # Set frame bg color
for widget in obj.winfo_children():
if '!label' in str(widget):
widget.config(bg=bg_hex) # Set label bg color
最后,将“按钮”命令更改为command=self.controller.pick_color_bg
。
通过这些更改,我可以消除对全局变量的需求。
答案 0 :(得分:1)
在函数pick_color()
中,您将创建一个Tk()
的新实例,该实例将获得新的颜色:
Master().update() # Creates a new root window!
要更改现有根窗口的颜色,必须保存对其的引用。另外,您还必须在类Master()
中编写一个函数,以更新bg颜色。调用update()
时,颜色不会自动更新,必须为每帧配置背景色。
更多
我很难在不重写代码的情况下阅读您的代码。您将名称Master
用于实例化根窗口的类。我将其称为Application
或与名称master
类似的名称通常表示“ master and server”或“ parent”中的master。另外,您使用名称frame
(通常是框架的名称)作为不同页面类实例(HomePage等)的名称。这使其难以阅读。就像用红色字母写的蓝色一词一样。
我会用更具描述性的名称来重写它,这样更容易掌握。这样,问题将更易于发现和纠正。
甚至更多
花点时间看一下,但这是一个如何进行较小更改的示例:
import tkinter as tk
from tkinter import ttk
from tkinter import colorchooser
bg_hex = '#f0f0f0f0f0f0' #default background color
def pick_color():
global bg_hex
bg_color = colorchooser.askcolor()
bg_hex = bg_color[1]
root.update_color() # Call function for updating color
print(bg_hex)
class Master(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side='top', fill='both', expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (HomePage, PageOne, PageTwo, Settings):
frame = F(container, self)
self.frames[F] = frame
frame.config(bg = bg_hex)
frame.grid(row=0, column=0, sticky='nsew')
self.show_frame(HomePage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
def update_color(self):
# Loop through pages and contained widgets and set color
for cls, obj in self.frames.items():
obj.config(bg=bg_hex) # Set frame bg color
for widget in obj.winfo_children():
if '!label' in str(widget):
widget.config(bg=bg_hex) # Set label bg color
class HomePage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text='Home Page', font=('Verdana', 12), bg=bg_hex)
label.pack(pady=5)
button1 = tk.Button(self, text='Page One', command=lambda: controller.show_frame(PageOne))
button1.pack(pady=5, ipadx=2)
button2 = tk.Button(self, text='Page Two', command=lambda: controller.show_frame(PageTwo))
button2.pack(pady=5)
button3 = tk.Button(self, text='Settings', command=lambda: controller.show_frame(Settings))
button3.pack(side='bottom', pady=10)
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Page One', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2, pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Page Two', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2,pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
class Settings(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
tk.Label(self, text='Settings', font='Verdana 14 bold underline', bg=bg_hex).grid(row=0, columnspan=2,pady=5)
button1 = tk.Button(self, text='Back to Home', command=lambda: controller.show_frame(HomePage))
button1.grid()
button2 = tk.Button(self, text='Choose Background', command= pick_color)
button2.grid()
root = Master() # Save a reference to the root window
root.mainloop()
我建议不要通过全局范围内的函数来更改颜色。我认为最好将其作为Master()
类的函数。然后,您将不必使用全局变量。