python-3.x - 更改背景颜色时打开新的 Tk 窗口
问题描述
我有一个包含多个框架的 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 窗口。
**更新代码以反映没有全局变量,希望它可以帮助其他人。
我self.controller = controller
在每个 Frame 类下添加,组合成 1 个函数pick_color
并color_update
放在 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
最后,将 Button 命令更改为command=self.controller.pick_color_bg
. 通过这些更改,我能够消除对全局变量的需求。
解决方案
在函数pick_color()
中,您创建一个Tk()
获取新颜色的新实例:
Master().update() # Creates a new root window!
要更改现有根窗口的颜色,您必须保存对它的引用。此外,您还必须在类中编写一个Master()
更新背景颜色的函数。调用时颜色不会自动更新update()
,您必须为每个帧配置 bg 颜色。
多一点
我无法在不重写代码的情况下阅读您的代码。您使用Master
实例化根窗口的类的名称。我会称它为Application
或类似名称,因为名称master
通常表示“主服务器”或“父服务器”中的主服务器。您还可以使用frame
通常是框架名称的 name 作为不同页面类实例(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()
类的功能。那么你就不必使用全局变量了。
推荐阅读
- python - 如何在 Django 中正确使用 slug url?
- python - 我该如何解决这个问题。当我尝试导入 tensorflow 时出现错误
- mysql - 无法更改时间戳列以将默认值设置为 current_timestamp
- reactjs - 如何使用另一种状态的状态 onClick 设置一种状态的状态
- python - 改善使用 mnist 数据集训练的神经网络的真实结果
- c# - C# Windows 异步 Ping 网络 - 每次运行的结果不同
- python - 哪些函数不能在 Python 中修饰?
- c# - 如何使用 OpenIddict 使/注销刷新和访问令牌(使用内存数据库)
- python - 在完成后保留所有列的熊猫中分组和过滤
- java - 如何将两个具有相同长度的数组相乘并返回具有这些值的新数组?