I followed this tutorial in creating a very simple text-editor app using Python's Tkinter
. What I wanted to do was add the option of using a checkbutton
, so when checked
, the theme of the text-editor would change to dark-mode theme and when unchecked
, would return to the default white theme. How can I do this?
I tried binding a function the checkbutton
where it would check the state and depending on the state, change the variables of the frames in the window. For example, if it was:
frame = tk.Frame(colour=white)
as the default, in the function I would put:
frame = tk.Frame(colour=white)
Even to me, this didn't look right. (I know the format is incorrect.)
Here the code (without my attempt at doing the dark-mode):
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
def open_file():
"""Open a file for editing."""
filepath = askopenfilename(
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
)
if not filepath:
return
txt_edit.delete(1.0, tk.END)
with open(filepath, "r") as input_file:
text = input_file.read()
txt_edit.insert(tk.END, text)
window.title(f"Simple Text Editor - {filepath}")
def save_file():
"""Save the current file as a new file."""
filepath = asksaveasfilename(
defaultextension="txt",
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],
)
if not filepath:
return
with open(filepath, "w") as output_file:
text = txt_edit.get(1.0, tk.END)
output_file.write(text)
window.title(f"Simple Text Editor - {filepath}")
window = tk.Tk()
window.title("Simple Text Editor")
window.rowconfigure(0, minsize=800, weight=1)
window.columnconfigure(1, minsize=800, weight=1)
txt_edit = tk.Text(window)
fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)
btn_open = tk.Button(fr_buttons, text="Open", command=open_file)
btn_save = tk.Button(fr_buttons, text="Save As...", command=save_file)
btn_open.grid(row=0, column=0, sticky="ew", padx=5, pady=5)
btn_save.grid(row=1, column=0, sticky="ew", padx=5)
fr_buttons.grid(row=0, column=0, sticky="ns")
txt_edit.grid(row=0, column=1, sticky="nsew")
window.mainloop()
We can create our GUI inside a method of a class. We can then define another method that kills the GUI, changes the variables that set our parameters for the theme and then restarts the GUI.
This might seem like alot of code, but once it is set up, it is very scalable and works not only for colour, but also other attributes. You can just loop through all the appropriate widgets you want.
Check out the following code:
import tkinter as tk
class App():
# Here, set everything up you want to override later, when restarting the GUI
def __init__(self):
self.color_scheme('dark') # This determines the mode the GUI starts up in.
self.font = ('Serif', 12)
# This will be shown on the button (when dark mode is active it needs to say "light theme")
self.theme_btn_text = 'Light Theme'
self.mainGUI() # Call the actual GUI and Inistialize with the standard Settings. This has to be AFTER all the setup
def mainGUI(self):
# Set up Root window
self.root = tk.Tk()
self.root.title('A title')
# whenever we style items, we use the attributes as colors. These attributes are defined in the function below.
self.root.configure(bg=self.bg)
# Set up buttons (only the unique elements)
self.btn1 = tk.Button(self.root,
text='Random Text')
self.theme_btn = tk.Button(self.root,
text=self.theme_btn_text,
command=lambda: self.theme_switch())
# Set up the attributes that all buttons have in common and pack them (or better use grid)
# Style them however you want
for btn in [self.btn1, self.theme_btn]:
btn.configure(bg=self.bg,
fg=self.fg,
activebackground=self.bg,
borderwidth=0)
btn.pack(padx=20, pady=20)
# Don't forget that everything needs to be between the TK() and the mainloop()
self.root.mainloop()
# Create the method that sets the colours of the class, depending on the active theme.
# This is used in the __init__ method to create the first theme, but also by the theme_switch method below.
def color_scheme(self, mode):
if mode == 'dark':
self.bg, self.fg, self.ac1, self.ac2 = ('#282828', 'white', '#404040y', '#B3B3B3')
if mode == 'light':
self.bg, self.fg, self.ac1, self.ac2 = ('#FBF8F1', 'black', '#F7ECDE', '#E9DAC1')
# This could of course also be placed inside the theme_switch method directly. But I like to use it for other things too.
def restart_GUI(self):
self.root.destroy()
self.mainGUI()
# Here we decide on whether we need to switch from light to dark or the other way around by looking at the color used at the moment the method is called via button press
def theme_switch(self):
if self.bg == '#282828':
self.color_scheme('light')
# We change the text to match the opposite theme
self.theme_btn_text = 'Dark Theme'
elif self.bg == '#FBF8F1':
self.color_scheme('dark')
self.theme_btn_text = 'Light Theme'
self.restart_GUI()
# Finally, we initiate an object of our class to start the GUI
x = App()
Hope this helps someone, Of course the two approaches can easily be combined. extended for other attributes and other widgets etc.
All the best!
You Can Do By Installing The Module ttkthemes
pip install ttkthemes
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedStyle
app = tk.Tk()
app.geometry("200x400")
app.title("Changing Themes")
# Setting Theme
style = ThemedStyle(app)
style.set_theme("scidgrey")
# Button Widgets
Def_Btn = tk.Button(app,text='Default Button')
Def_Btn.pack()
Themed_Btn = ttk.Button(app,text='Themed button')
Themed_Btn.pack()
# Scrollbar Widgets
Def_Scrollbar = tk.Scrollbar(app)
Def_Scrollbar.pack(side='right',fill='y')
Themed_Scrollbar = ttk.Scrollbar(app,orient='horizontal')
Themed_Scrollbar.pack(side='top',fill='x')
# Entry Widgets
Def_Entry = tk.Entry(app)
Def_Entry.pack()
Themed_Entry = ttk.Entry(app)
Themed_Entry.pack()
app.mainloop()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.