In this article, we'll delve into some of the more intricate aspects of Tkinter, exploring advanced techniques that will empower you to create even more powerful and polished GUI applications. Throughout our exploration, we'll uncover invaluable tools such as the ttk
module for enhanced widget styling, the Canvas widget for versatile graphics rendering, and the Grid geometry manager for precise layout control. From custom themes to file handling strategies, gear up to elevate your Tkinter expertise to the next level.
If you are new to Tkinter, I highly recommend you to thoroughly review this article or the official documentation. Familiarizing yourself with its contents will provide a solid foundation for understanding and effectively utilizing Tkinter.
In the code snippets provided, add these lines in the beginning:
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
window.geometry("457x335")
and this line at the end:
window.mainloop()
Custom Styles and Themes
Tkinter enables customized visual presentation through custom styles and themes, using the ttk
module for personalized widget designs, ensuring consistency across platforms.
To deepen our understanding, let's personalize our textbox, button, and label by customizing their appearance:
import tkinter as tk
from tkinter import ttk
def submit_text():
text = text_entry.get()
text_label.config(text=text, font=("Times New Roman", 12, "bold"), foreground="green") #customize label
window = tk.Tk()
window.geometry("457x335")
window.title("Custom Styles")
style = ttk.Style() #to define custom styles
style.configure("Custom.TEntry", foreground="blue", fieldbackground="lightblue") #customize textbox
style.configure("Custom.TButton", foreground="red", background="red") #customize button
text_entry = ttk.Entry(window, width=30, style="Custom.TEntry")
text_entry.pack(padx=10, pady=10)
submit_button = ttk.Button(window, text="Submit", command=submit_text, style="Custom.TButton") #sends entered text to the submit_text() function
submit_button.pack(padx=10, pady=5)
text_label = ttk.Label(window)
text_label.pack(padx=10, pady=10)
window.mainloop()

The submit_text
function retrieves your text from the text_entry
textbox and updates the text_label
with it. The label's appearance is customized using Times New Roman font, size 12, bold, and green color. Custom styles (Custom.TEntry
for the textbox and Custom.TButton
for the button) are defined and configured using the ttk.Style()
method to set properties like foreground
and background
colors.
Integration with Python Libraries
Tkinter can be integrated with other Python libraries and tools to enhance its functionality:
Integration with Matplotlib: You can make your Tkinter app more informative by adding interactive charts to display data trends or visualizations. By integrating Matplotlib, a popular Python library for creating charts and graphs, you can easily embed dynamic plots directly into your Tkinter windows.
Integration with Scikit-learn: You can combine Tkinter with Scikit-learn to develop GUI applications for machine learning tasks such as classification, regression, and clustering. This integration enables us to build interactive interfaces for training models, evaluating performance, and making predictions.
In order to install sklearn library locally, run the command: `pip install scikit-learn`
Ensure local compatibility by installing `matplotlib` and `matplotlib.backends.backend_tkagg` before running this code.
Let's delve into the concept using an example of Linear Regression applied to predict outcomes for the Diabetes dataset:
import tkinter as tk
from tkinter import ttk #for themed widgets
import matplotlib.pyplot as plt
from sklearn.datasets import load_diabetes
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
diabetes = load_diabetes() #Load the dataset
X_train, X_test, y_train, y_test = train_test_split(diabetes.data, diabetes.target, test_size=0.2, random_state=42)
window = tk.Tk()
window.geometry("650x500")
window.title("Diabetes Linear Regression")
def train_and_plot():
model = LinearRegression()
model.fit(X_train, y_train) #train
y_pred_train = model.predict(X_train) #predict
y_pred_test = model.predict(X_test)
mse_train = mean_squared_error(y_train, y_pred_train) #calculate mean squared error
mse_test = mean_squared_error(y_test, y_pred_test)
plt.figure(figsize=(8, 6)) #create the plot
plt.scatter(y_test, y_pred_test, color='blue')
plt.plot([min(y_test), max(y_test)], [min(y_test), max(y_test)], color='red', linestyle='--')
plt.xlabel("Actual")
plt.ylabel("Predicted")
plt.title("Linear Regression Graph")
plt.grid(True)
plt.tight_layout() #ensures the plot fits within the Tkinter window
result_label.config(text=f"Train MSE: {mse_train:.2f}\tTest MSE: {mse_test:.2f}")
canvas = FigureCanvasTkAgg(plt.gcf(), master=window) #converts the plot into a format that can be displayed in the Tkinter window
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1) #adds the canvas widget to the Tkinter window.
train_button = ttk.Button(window, text="Train and Plot", command=train_and_plot)
train_button.pack(pady=10)
result_label = ttk.Label(window, text="")
result_label.pack()
window.mainloop()

The train_and_plot
function trains a linear regression model on the dataset, predicts the target values, calculates the mean squared error for both training and testing sets, and then plots the predicted values against the actual values using matplotlib. It also displays the calculated mean squared errors on your GUI window.
Advanced Widgets
Tkinter provides a wide range of widgets beyond the basic ones like labels and buttons. You can explore and utilize widgets like treeview, notebook, progressbar, etc. to create sophisticated user interfaces.
A treeview to display hierarchical data, like a file explorer.
import tkinter as tk
from tkinter import ttk #for themed widgets
window = tk.Tk()
window.geometry("640x300")
tree = ttk.Treeview(window)
tree["columns"] = ("Fruits", "Quantity")
tree.heading("#0", text="Sr. No.") #First column (index=0) will be Sr. No.
tree.heading("Fruits", text="Fruits")
tree.heading("Quantity", text="Quantity (kg)")
tree.insert("", tk.END, text="1", values=("Apple", 30))
tree.insert("", tk.END, text="2", values=("Orange", 25))
tree.insert("", tk.END, text="3", values=("Mango", 29))
tree.pack()
window.mainloop()

The Treeview widget tree
consists of two columns: "Fruits" and "Quantity (kg)". The heading
method sets headings for each column, and the insert
method adds items to the Treeview. Each item is inserted with a unique identifier "Sr. No." and its corresponding values for "Fruits" and "Quantity" are entered.
A notebook to organize your app into different tabs, like in a web browser.
import tkinter as tk
from tkinter import ttk #for themed widgets
window = tk.Tk()
window.geometry("457x335")
notebook = ttk.Notebook(window)
tab1 = ttk.Frame(notebook)
tab2 = ttk.Frame(notebook)
tab3 = ttk.Frame(notebook)
label1 = tk.Label(tab1, text="This is Tab 1") #for tab 1
label1.pack()
entry2 = tk.Entry(tab2) #for tab 2
entry2.pack()
check_var = tk.BooleanVar()
check_button3 = tk.Checkbutton(tab3, text="This is Tab 3", variable=check_var) #for tab 3
check_button3.pack()
notebook.add(tab1, text="Tab 1")
notebook.add(tab2, text="Tab 2")
notebook.add(tab3, text="Tab 3")
notebook.pack()
window.mainloop()



It creates a Notebook widget notebook
, which allows 3 tabs to be displayed, namely Tab 1
, Tab 2
, and Tab 3
, ceated using ttk.Frame
. Tab 1
contains a Label widget with the text "This is Tab 1". Tab 2
contains an Entry widget for user input. Tab 3
contains a Checkbutton widget with the text "This is Tab 3".
A progressbar to show how far along a task is, like when you're downloading a file.
import tkinter as tk
from tkinter import ttk
import time
def start_task():
progress_bar.start(10) #start the progressbar (animation is updated every 10 milliseconds)
window.after(3000, stop_task) #simulate task completion after 3 seconds
def stop_task():
progress_bar.stop() #stop the progressbar
window = tk.Tk()
window.geometry("457x335")
progress_bar = ttk.Progressbar(window, orient="horizontal", length=200, mode="indeterminate")
progress_bar.pack()
start_button = tk.Button(window, text="Start Task", command=start_task)
start_button.pack(pady=20)
window.mainloop()

When the "Start Task" button is clicked, it triggers the start_task
function, which starts the progress bar animation using the start
method. The after
method is used to schedule the stop_task
function to run after 3 seconds. The stop_task
function stops the progress bar animation using the stop
method.
Advanced Layout Management
Advanced Layout Management can be used to make your Tkinter app look polished. Layout management helps you move widgets around and make your app look just the way you want using grid
, place
, and pack
managers.
Grid
You can place widgets in rows and columns, and they will organize neatly into place.
import tkinter as tk
window = tk.Tk()
window.geometry("457x335")
label1 = tk.Label(window, text="Subject")
label2 = tk.Label(window, text="Marks")
entry1 = tk.Entry(window) #Widgets
entry2 = tk.Entry(window)
entry3 = tk.Entry(window)
entry4 = tk.Entry(window)
label1.grid(row=0, column=0) #Layout
label2.grid(row=0, column=1)
entry1.grid(row=1, column=0)
entry2.grid(row=1, column=1)
entry3.grid(row=2, column=0)
entry4.grid(row=2, column=1)
window.mainloop()

This code sets up 2 labels Subject
and Marks
and 4 entry widgets for data input. The layout is organized with Subject
in row 0, column 0, Marks
in row 0, column 1. Entry widgets entry1
and entry2
occupy row 1, columns 0 and 1 respectively, while entry3
and entry4
are in row 2, columns 0 and 1.
Pack
You can stack widgets on top of each other or arrange them side by side, and Tkinter will figure out how to fit them all in.
import tkinter as tk
window = tk.Tk()
window.geometry("457x335")
button1 = tk.Button(window, text="Left") #Widgets
button2 = tk.Button(window, text="Top")
button3 = tk.Button(window, text="Right")
button4 = tk.Button(window, text="Bottom")
button1.pack(side=tk.LEFT) #Layout
button2.pack(side=tk.TOP)
button3.pack(side=tk.RIGHT)
button4.pack(side=tk.BOTTOM)
window.mainloop()

The buttons button1
, button2
, button3
and button4
are positioned by providing the side
parameter with values tk.LEFT
, tk.TOP
, tk.RIGHT
, or tk.BOTTOM
respectively.
Place
You can specify exactly where you want each widget to go by giving it coordinates, like x and y coordinates on a graph.
import tkinter as tk
window = tk.Tk()
window.geometry("457x335")
label1 = tk.Label(window, text="x_50_y_50") #Widgets
label2 = tk.Label(window, text="x_200_y_200")
label1.place(x=50, y=50) #Layout
label2.place(x=200, y=200)
window.mainloop()

The place
method is used to position label widgets. label1
is placed at coordinates (50, 50), and label2
is placed at coordinates (200, 200).
File Handling
Tkinter facilitates file handling through the filedialog
tool, enabling users to interactively select files on their computer. With this feature, your application can support tasks like creating, opening, saving, and editing various file types such as documents, images, or spreadsheets.
Let's understand this using an example:
import tkinter as tk
from tkinter import filedialog
def open_file():
file_path = filedialog.askopenfilename() #opens a dialog window to select an existing file or create a new one
if not file_path:
return
with open(file_path, 'a+') as file: #'a+' to append the text to the file
file.write("January\n")
file.write("February\n")
file.write("March\n")
file.write("April\n")
file.write("May\n")
status_label.config(text=f"File '{file_path}' has been written and closed.")
window = tk.Tk()
window.geometry("457x335")
window.title("File Writer")
open_button = tk.Button(window, text="Open a File", command=open_file)
open_button.pack(pady=20)
status_label = tk.Label(window, text="")
status_label.pack()
root.mainloop()



When clicked, the button "Open a File" triggers the open_file
function, which opens a dialog window allowing you to select an existing file or create a new one. If a file is selected, the code appends the strings "January", "February"..."May" to the file and the file is closed. The status_label
is then updated to display a message confirming the file write operation.
The file will automatically be closed when the `with` block is exited. However, you may explicitly close the file by calling `file.close()`.
Modal and Modeless Dialogs
Tkinter offers both modal and modeless dialogs, ideal for user input, confirmation messages, or notifications. The tkinter.messagebox
module provides standard message boxes, while custom dialog windows can be created using Toplevel
widgets.
Modal dialogs are windows that require the user to interact with them before returning to the main application window. They typically block interaction with other windows in the application until they are closed.
import tkinter as tk
from tkinter import messagebox
def show_modal_dialog():
messagebox.showinfo("Modal Dialog", "Pay attention to this dialog box!") #does not let you proceed until you click the "OK" button
window = tk.Tk()
window.geometry("457x335")
window.title("Modal Dialog Example")
modal_button = tk.Button(window, text="Click me", command=show_modal_dialog)
modal_button.pack(padx=20, pady=10)
window.mainloop()

Modeless dialogs are windows that allow the user to interact with both the dialog and the main application window simultaneously. They do not block interaction with other windows in the application, allowing the user to switch between them freely.
import tkinter as tk
def show_modeless_dialog():
modeless_dialog = tk.Toplevel(window) #allows you to interact with other open windows
modeless_dialog.title("Modeless Dialog")
modeless_dialog.geometry("250x100")
label = tk.Label(modeless_dialog, text="Have a nice day!")
label.pack(padx=20, pady=10)
window = tk.Tk()
window.geometry("457x335")
window.title("Modeless Dialog Example")
modeless_button = tk.Button(window, text="Click me", command=show_modeless_dialog)
modeless_button.pack(padx=20, pady=10)
window.mainloop()

When clicked, the button "Click me" triggers the show_modeless_dialog
function, which creates a modeless dialog box using the Toplevel
widget. It will not hinder your interaction with the other windows.
Using a class for modeless dialogs can organize and encapsulate dialog functionality, particularly for more intricate dialogs with multiple components and interactions.
Conclusion
Tkinter is a versatile Python GUI framework that enhances user interaction and functionality. With features like custom themes, threading, file handling, dialogs, layout management, advanced widgets, and integration with libraries like Matplotlib and scikit-learn, Tkinter empowers developers to create dynamic desktop applications. By leveraging these capabilities, developers can craft unique GUIs that elevate user experience, making Tkinter a top choice for Python GUI projects.