I am making an expense tracker as a fun project. I have encountered an issue where the colour choosing method I am using inside the frame class isn’t working, could someone help please?
Here is my code:
import tkinter as tk
from tkinter import ttk, colorchooser, messagebox
class ExpenseTracker(tk.Tk):
def __init__(self):
super().__init__()
self.title("Expense Tracker")
self.geometry("700x700")
self.minsize(700, 700)
self.login = Login(self)
self.mainloop()
class Login(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
tk.Label(text="Enter Username:").place(relx=0.5, rely=0.36, anchor=tk.CENTER)
tk.Label(text="Enter Password:").place(relx=0.5, rely=0.46, anchor=tk.CENTER)
change_colour = tk.Button(text="Background Colour", command=self.change_colour)
change_colour.place(relx=0.9, rely=0.1, anchor=tk.CENTER)
username_entry = tk.Entry()
username_entry.place(relx=0.5, rely=0.4, anchor=tk.CENTER)
password_entry = tk.Entry()
password_entry.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
login_box = tk.Button(text="Login")
login_box.place(relx=0.5, rely=0.55, anchor=tk.CENTER)
self.grid()
def change_colour(self):
color = colorchooser.askcolor()[1]
self.configure(bg=color)
ExpenseTracker()
At first, the login class inherited from "ttk.Frame", which I wanted but I was getting an " unknown option "-bg"" error. Then, I changed it to inherit from "tk.Frame", which stopped the error from happening, but the background still doesn’t change when I use the change colour button.
>Solution :
You originally encountered errors because ttk.Frame doesn’t support background color changes with the bg option. Switching to tk.Frame resolved this, as it supports direct background customization.
Your use of self.grid() without parameters might not properly size or display the Login frame. Consider using self.pack(expand=True, fill=tk.BOTH) for better control and visibility.
The change_colour function only alters the frame’s background, not the widgets on it. To uniformly change colors, you must set the background of each widget within the frame manually when the color is changed.
Here’s an updated version of your Login class which addresses these issues:
import tkinter as tk
from tkinter import ttk, colorchooser, messagebox
class ExpenseTracker(tk.Tk):
def __init__(self):
super().__init__()
self.title("Expense Tracker")
self.geometry("700x700")
self.minsize(700, 700)
self.login = Login(self)
self.mainloop()
class Login(tk.Frame):
def __init__(self, parent):
super().__init__(parent, bg='white') # Set default background color
self.pack(expand=True, fill=tk.BOTH) # Use pack with expand and fill for proper sizing
tk.Label(self, text="Enter Username:", bg='white').place(relx=0.5, rely=0.36, anchor=tk.CENTER)
tk.Label(self, text="Enter Password:", bg='white').place(relx=0.5, rely=0.46, anchor=tk.CENTER)
self.change_colour_btn = tk.Button(self, text="Background Colour", command=self.change_colour)
self.change_colour_btn.place(relx=0.9, rely=0.1, anchor=tk.CENTER)
self.username_entry = tk.Entry(self)
self.username_entry.place(relx=0.5, rely=0.4, anchor=tk.CENTER)
self.password_entry = tk.Entry(self)
self.password_entry.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
self.login_box = tk.Button(self, text="Login")
self.login_box.place(relx=0.5, rely=0.55, anchor=tk.CENTER)
def change_colour(self):
color = colorchooser.askcolor()[1]
if color: # Check if a color was actually selected
self.configure(bg=color) # Change the background of the frame
# Also change the background of all widgets
for widget in [self, self.change_colour_btn, self.username_entry, self.password_entry, self.login_box]:
widget.configure(bg=color)
ExpenseTracker()
The frame fills the entire parent window using pack(expand=True, fill=tk.BOTH). All the widgets on the frame will change their background color along with the frame itself when you choose a new color. It handles the case where the user might cancel the color dialog by checking if color is not None before attempting to change the background colors.
Hope this helps 🙂