Tkinter-built-in GUI tool

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

History and Architecture of Tkinter

Tkinter was created in the early 1990s as a Python wrapper for the Tk GUI toolkit. Tk, in turn, was developed by John Ousterhout at the University of California, Berkeley. Over more than 30 years, the library has evolved significantly while preserving its philosophy of simplicity and reliability.

The architecture of Tkinter is based on event‑driven programming. The core component is the main event loop, which waits for user actions and responds by invoking the appropriate callback functions.

Installation and First Run

Checking Tkinter Availability

Tkinter is part of the Python standard library and usually does not require a separate installation. To verify its availability, run:

python -c "import tkinter; print('Tkinter is available')"

Installation on Different Operating Systems

Windows: Tkinter is installed automatically with Python.

macOS: Included in the standard Python distribution.

Linux (Ubuntu/Debian):

sudo apt-get install python3-tk

Linux (CentOS/RHEL):

sudo yum install tkinter
# or for newer versions
sudo dnf install python3-tkinter

Creating Your First Application

import tkinter as tk

# Create the main window
window = tk.Tk()
window.title("My First Application")
window.geometry("400x300")
window.resizable(True, True)

# Start the main loop
window.mainloop()

Main Tkinter Components

Root Window

The root window is the base element of any Tkinter application. All other widgets must be placed inside it or inside its child windows.

import tkinter as tk

root = tk.Tk()
root.title("Window Title")
root.geometry("800x600+100+50")  # width x height + offset_x + offset_y
root.minsize(300, 200)          # minimum size
root.maxsize(1200, 800)         # maximum size
root.configure(bg='lightblue')  # background color

Core Widgets and Their Usage

Label

Label is used to display text or images that the user cannot edit.

label = tk.Label(
    window,
    text="Information label",
    font=("Arial", 14),
    fg="blue",
    bg="white",
    anchor="center"
)
label.pack(pady=10)

Button

Button is an interactive element that triggers actions.

def button_click():
    print("Button pressed!")

button = tk.Button(
    window,
    text="Click Me",
    command=button_click,
    font=("Arial", 12),
    bg="green",
    fg="white",
    width=15,
    height=2
)
button.pack(pady=5)

Entry

Entry is intended for single‑line text input.

entry_var = tk.StringVar()
entry = tk.Entry(
    window,
    textvariable=entry_var,
    font=("Arial", 12),
    width=30
)
entry.pack(pady=5)

# Retrieve the value
def get_entry_value():
    value = entry_var.get()
    print(f"Entered: {value}")

Text

Text provides a multi‑line editable text area.

text_widget = tk.Text(
    window,
    height=10,
    width=50,
    font=("Courier", 10),
    wrap=tk.WORD
)
text_widget.pack(pady=10)

# Insert text
text_widget.insert(tk.END, "Initial text\n")

# Get all text
def get_text_content():
    content = text_widget.get("1.0", tk.END)
    return content

Checkbutton

Checkbutton lets the user choose a yes/no option.

check_var = tk.BooleanVar()
checkbox = tk.Checkbutton(
    window,
    text="I agree to the terms",
    variable=check_var,
    command=lambda: print(f"State: {check_var.get()}")
)
checkbox.pack(pady=5)

Radiobutton

Radiobutton is used for selecting one option from a group.

radio_var = tk.StringVar(value="option1")

radio1 = tk.Radiobutton(
    window,
    text="Option 1",
    variable=radio_var,
    value="option1"
)
radio2 = tk.Radiobutton(
    window,
    text="Option 2",
    variable=radio_var,
    value="option2"
)
radio1.pack()
radio2.pack()

Listbox

Listbox displays a list of selectable items.

listbox = tk.Listbox(
    window,
    height=6,
    selectmode=tk.SINGLE
)

items = ["Item 1", "Item 2", "Item 3"]
for item in items:
    listbox.insert(tk.END, item)

listbox.pack(pady=10)

def on_select(event):
    selection = listbox.curselection()
    if selection:
        selected_item = listbox.get(selection[0])
        print(f"Selected: {selected_item}")

listbox.bind("<<ListboxSelect>>", on_select)

OptionMenu

OptionMenu creates a drop‑down list of choices.

option_var = tk.StringVar(value="Select an option")
options = ["Option A", "Option B", "Option C"]

option_menu = tk.OptionMenu(window, option_var, *options)
option_menu.pack(pady=10)

Scale

Scale lets the user pick a numeric value within a defined range.

scale_var = tk.DoubleVar()
scale = tk.Scale(
    window,
    from_=0,
    to=100,
    orient=tk.HORIZONTAL,
    variable=scale_var,
    label="Choose a value"
)
scale.pack(pady=10)

Canvas

Canvas is intended for drawing graphical elements.

canvas = tk.Canvas(
    window,
    width=400,
    height=300,
    bg="white"
)
canvas.pack(pady=10)

# Draw various shapes
canvas.create_line(0, 0, 400, 300, fill="red", width=2)
canvas.create_rectangle(50, 50, 150, 100, fill="blue", outline="black")
canvas.create_oval(200, 50, 300, 150, fill="green")
canvas.create_text(200, 200, text="Canvas text", font=("Arial", 16))

Widget Geometry Managers

Pack Manager

Pack arranges widgets sequentially in the chosen direction.

# Vertical packing
label1 = tk.Label(window, text="Label 1", bg="red")
label1.pack(side=tk.TOP, fill=tk.X, padx=5, pady=2)

label2 = tk.Label(window, text="Label 2", bg="green")
label2.pack(side=tk.TOP, fill=tk.X, padx=5, pady=2)

# Horizontal packing
button1 = tk.Button(window, text="Button 1")
button1.pack(side=tk.LEFT, padx=5)

button2 = tk.Button(window, text="Button 2")
button2.pack(side=tk.RIGHT, padx=5)

Grid Manager

Grid places widgets in a table of rows and columns.

# Simple login form
tk.Label(window, text="Username:").grid(row=0, column=0, sticky="e", padx=5, pady=5)
login_entry = tk.Entry(window)
login_entry.grid(row=0, column=1, padx=5, pady=5)

tk.Label(window, text="Password:").grid(row=1, column=0, sticky="e", padx=5, pady=5)
password_entry = tk.Entry(window, show="*")
password_entry.grid(row=1, column=1, padx=5, pady=5)

login_button = tk.Button(window, text="Log In")
login_button.grid(row=2, column=0, columnspan=2, pady=10)

Place Manager

Place allows precise positioning of widgets by coordinates.

button1 = tk.Button(window, text="Absolute Position")
button1.place(x=50, y=100)

button2 = tk.Button(window, text="Relative Position")
button2.place(relx=0.5, rely=0.5, anchor="center")

Event Handling

Basic Event Handling

Tkinter supports a wide range of events from the keyboard, mouse, and system.

def on_key_press(event):
    print(f"Key pressed: {event.keysym}")

def on_mouse_click(event):
    print(f"Mouse click at: ({event.x}, {event.y})")

def on_window_close():
    if messagebox.askyesno("Confirmation", "Close the application?"):
        window.destroy()

# Bind events
window.bind("<Key>", on_key_press)
window.bind("<Button-1>", on_mouse_click)
window.protocol("WM_DELETE_WINDOW", on_window_close)

Key Event Types

Keyboard:

  • <Key> – any key
  • <Return> – Enter
  • <Escape> – Escape
  • <Control-s> – Ctrl+S

Mouse:

  • <Button-1> – left mouse button
  • <Button-3> – right mouse button
  • <Double-Button-1> – double‑click
  • <Motion> – mouse movement

Window:

  • <Configure> – window resize
  • <FocusIn> – focus gained
  • <FocusOut> – focus lost

Working with Dialog Windows

Standard Message Dialogs

from tkinter import messagebox

# Information message
messagebox.showinfo("Info", "Operation completed successfully")

# Warning
messagebox.showwarning("Warning", "Proceed with caution")

# Error
messagebox.showerror("Error", "An error occurred")

# Yes/No question
result = messagebox.askyesno("Confirm", "Continue?")

# Yes/No/Cancel question
result = messagebox.askyesnocancel("Save", "Save changes?")

File Selection Dialogs

from tkinter import filedialog

# Open file
filename = filedialog.askopenfilename(
    title="Select a file",
    filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
)

# Save file
filename = filedialog.asksaveasfilename(
    title="Save As",
    defaultextension=".txt",
    filetypes=[("Text files", "*.txt")]
)

# Choose directory
directory = filedialog.askdirectory(title="Select a folder")

Simple Input Dialogs

from tkinter import simpledialog

# String input
name = simpledialog.askstring("Input", "Enter your name:")

# Integer input
age = simpledialog.askinteger("Input", "Enter your age:", minvalue=0, maxvalue=120)

# Float input
price = simpledialog.askfloat("Input", "Enter the price:", minvalue=0.0)

Additional Windows (Toplevel)

def create_new_window():
    new_window = tk.Toplevel(window)
    new_window.title("Additional Window")
    new_window.geometry("300x200")
    new_window.grab_set()  # Modal window
    
    tk.Label(new_window, text="This is a new window").pack(pady=20)
    
    close_button = tk.Button(
        new_window,
        text="Close",
        command=new_window.destroy
    )
    close_button.pack(pady=10)

create_window_button = tk.Button(
    window,
    text="Open New Window",
    command=create_new_window
)
create_window_button.pack(pady=20)

Working with Tkinter Variables

Tkinter provides special variable classes for binding data to widgets.

# Different variable types
string_var = tk.StringVar(value="Initial value")
int_var = tk.IntVar(value=10)
double_var = tk.DoubleVar(value=3.14)
boolean_var = tk.BooleanVar(value=True)

# Bind to widgets
entry = tk.Entry(window, textvariable=string_var)
scale = tk.Scale(window, variable=int_var, from_=0, to=100)
checkbutton = tk.Checkbutton(window, variable=boolean_var)

# Track changes
def on_variable_change(*args):
    print(f"New value: {string_var.get()}")

string_var.trace("w", on_variable_change)

Creating Menus

Main Menu

def new_file():
    print("New file")

def open_file():
    filename = filedialog.askopenfilename()
    if filename:
        print(f"Opened file: {filename}")

def save_file():
    print("Save file")

def exit_app():
    window.quit()

def about():
    messagebox.showinfo("About", "Text editor v1.0")

# Create the main menu
menubar = tk.Menu(window)

# "File" menu
file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label="New", command=new_file, accelerator="Ctrl+N")
file_menu.add_command(label="Open", command=open_file, accelerator="Ctrl+O")
file_menu.add_command(label="Save", command=save_file, accelerator="Ctrl+S")
file_menu.add_separator()
file_menu.add_command(label="Exit", command=exit_app, accelerator="Ctrl+Q")

# "Help" menu
help_menu = tk.Menu(menubar, tearoff=0)
help_menu.add_command(label="About", command=about)

# Add menus to the menubar
menubar.add_cascade(label="File", menu=file_menu)
menubar.add_cascade(label="Help", menu=help_menu)

# Set the menu for the window
window.config(menu=menubar)

# Keyboard shortcuts
window.bind("<Control-n>", lambda e: new_file())
window.bind("<Control-o>", lambda e: open_file())
window.bind("<Control-s>", lambda e: save_file())

Context Menu

def show_context_menu(event):
    context_menu.post(event.x_root, event.y_root)

def copy_text():
    print("Copy")

def paste_text():
    print("Paste")

# Create the context menu
context_menu = tk.Menu(window, tearoff=0)
context_menu.add_command(label="Copy", command=copy_text)
context_menu.add_command(label="Paste", command=paste_text)

# Bind to right‑click
window.bind("<Button-3>", show_context_menu)

Styling and ttk

Using ttk for a Modern Look

from tkinter import ttk

# Create a style
style = ttk.Style()
style.theme_use('clam')  # modern theme

# Configure styles
style.configure(
    "Custom.TButton",
    font=("Arial", 12),
    foreground="white",
    background="blue"
)

# Use ttk widgets
ttk_button = ttk.Button(
    window,
    text="Modern Button",
    style="Custom.TButton"
)
ttk_button.pack(pady=10)

# Progress bar
progress = ttk.Progressbar(
    window,
    length=300,
    mode='determinate'
)
progress.pack(pady=10)
progress['value'] = 50

# Combobox
combo = ttk.Combobox(
    window,
    values=["Option 1", "Option 2", "Option 3"],
    state="readonly"
)
combo.pack(pady=10)

Table of Tkinter Methods and Functions

Category Method / Function Description Example
Main Classes      
  Tk() Creates the main window root = tk.Tk()
  Toplevel() Creates an additional window new_win = tk.Toplevel(root)
  mainloop() Starts the main event loop root.mainloop()
Widgets      
  Label() Text label tk.Label(root, text="Text")
  Button() Button tk.Button(root, text="OK", command=func)
  Entry() Entry field tk.Entry(root, width=20)
  Text() Multi‑line text area tk.Text(root, height=10)
  Checkbutton() Checkbutton tk.Checkbutton(root, text="Option")
  Radiobutton() Radiobutton tk.Radiobutton(root, text="Choice")
  Listbox() Listbox tk.Listbox(root, height=5)
  Scale() Scale tk.Scale(root, from_=0, to=100)
  Canvas() Canvas for drawing tk.Canvas(root, width=400, height=300)
  Frame() Widget container tk.Frame(root, relief="solid")
  Menu() Menu tk.Menu(root)
  OptionMenu() Drop‑down menu tk.OptionMenu(root, var, *options)
Geometry Management      
  pack() Sequential placement widget.pack(side=tk.TOP, fill=tk.X)
  grid() Table placement widget.grid(row=0, column=1)
  place() Absolute positioning widget.place(x=100, y=50)
Events      
  bind() Bind an event handler widget.bind("<Button-1>", handler)
  unbind() Unbind an event handler widget.unbind("<Button-1>")
  focus_set() Set focus widget.focus_set()
Variables      
  StringVar() String variable var = tk.StringVar(value="text")
  IntVar() Integer variable var = tk.IntVar(value=10)
  DoubleVar() Float variable var = tk.DoubleVar(value=3.14)
  BooleanVar() Boolean variable var = tk.BooleanVar(value=True)
Widget Methods      
  get() Retrieve value entry.get()
  set() Set value var.set("new value")
  insert() Insert text text.insert(tk.END, "text")
  delete() Delete text text.delete("1.0", tk.END)
  config() / configure() Change properties widget.config(text="new text")
  destroy() Destroy widget widget.destroy()
Dialogs      
  messagebox.showinfo() Information dialog messagebox.showinfo("Title", "Message")
  messagebox.showwarning() Warning dialog messagebox.showwarning("Attention", "Message")
  messagebox.showerror() Error dialog messagebox.showerror("Error", "Message")
  messagebox.askyesno() Yes/No question result = messagebox.askyesno("?", "Message")
  filedialog.askopenfilename() Open‑file dialog file = filedialog.askopenfilename()
  filedialog.asksaveasfilename() Save‑file dialog file = filedialog.asksaveasfilename()
  simpledialog.askstring() String input dialog text = simpledialog.askstring("Input", "?")
Window Geometry      
  geometry() Size and position root.geometry("800x600+100+50")
  minsize() Minimum size root.minsize(300, 200)
  maxsize() Maximum size root.maxsize(1200, 800)
  resizable() Allow resizing root.resizable(True, False)
  title() Window title root.title("My Application")

Practical Application Examples

Simple Calculator

import tkinter as tk
from tkinter import messagebox

class Calculator:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Calculator")
        self.window.geometry("300x400")
        self.window.resizable(False, False)
        
        self.expression = ""
        self.result_var = tk.StringVar()
        
        self.create_widgets()
    
    def create_widgets(self):
        # Result display
        result_frame = tk.Frame(self.window)
        result_frame.pack(fill=tk.X, padx=5, pady=5)
        
        result_entry = tk.Entry(
            result_frame,
            textvariable=self.result_var,
            font=("Arial", 16),
            justify="right",
            state="readonly"
        )
        result_entry.pack(fill=tk.X)
        
        # Buttons
        button_frame = tk.Frame(self.window)
        button_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        buttons = [
            ['C', '/', '*', 'Del'],
            ['7', '8', '9', '-'],
            ['4', '5', '6', '+'],
            ['1', '2', '3', '='],
            ['0', '.', '', '']
        ]
        
        for i, row in enumerate(buttons):
            for j, text in enumerate(row):
                if text:
                    if text == '0':
                        btn = tk.Button(
                            button_frame,
                            text=text,
                            font=("Arial", 14),
                            command=lambda t=text: self.button_click(t)
                        )
                        btn.grid(row=i, column=j, columnspan=2, sticky="nsew", padx=1, pady=1)
                    else:
                        btn = tk.Button(
                            button_frame,
                            text=text,
                            font=("Arial", 14),
                            command=lambda t=text: self.button_click(t)
                        )
                        btn.grid(row=i, column=j, sticky="nsew", padx=1, pady=1)
        
        # Configure grid
        for i in range(5):
            button_frame.grid_rowconfigure(i, weight=1)
        for j in range(4):
            button_frame.grid_columnconfigure(j, weight=1)
    
    def button_click(self, char):
        if char == 'C':
            self.expression = ""
        elif char == 'Del':
            self.expression = self.expression[:-1]
        elif char == '=':
            try:
                result = eval(self.expression)
                self.expression = str(result)
            except:
                messagebox.showerror("Error", "Invalid expression")
                self.expression = ""
        else:
            self.expression += char
        
        self.result_var.set(self.expression)
    
    def run(self):
        self.window.mainloop()

# Run the calculator
if __name__ == "__main__":
    calc = Calculator()
    calc.run()

Text Editor

import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import font

class TextEditor:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Text Editor")
        self.window.geometry("800x600")
        
        self.current_file = None
        self.is_modified = False
        
        self.create_menu()
        self.create_toolbar()
        self.create_text_area()
        self.create_status_bar()
        
        self.window.protocol("WM_DELETE_WINDOW", self.on_closing)
    
    def create_menu(self):
        menubar = tk.Menu(self.window)
        
        # File menu
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label="New", command=self.new_file, accelerator="Ctrl+N")
        file_menu.add_command(label="Open", command=self.open_file, accelerator="Ctrl+O")
        file_menu.add_command(label="Save", command=self.save_file, accelerator="Ctrl+S")
        file_menu.add_command(label="Save As", command=self.save_as_file)
        file_menu.add_separator()
        file_menu.add_command(label="Exit", command=self.on_closing)
        
        # Edit menu
        edit_menu = tk.Menu(menubar, tearoff=0)
        edit_menu.add_command(label="Undo", command=self.undo, accelerator="Ctrl+Z")
        edit_menu.add_command(label="Redo", command=self.redo, accelerator="Ctrl+Y")
        edit_menu.add_separator()
        edit_menu.add_command(label="Cut", command=self.cut, accelerator="Ctrl+X")
        edit_menu.add_command(label="Copy", command=self.copy, accelerator="Ctrl+C")
        edit_menu.add_command(label="Paste", command=self.paste, accelerator="Ctrl+V")
        
        menubar.add_cascade(label="File", menu=file_menu)
        menubar.add_cascade(label="Edit", menu=edit_menu)
        
        self.window.config(menu=menubar)
        
        # Keyboard shortcuts
        self.window.bind("<Control-n>", lambda e: self.new_file())
        self.window.bind("<Control-o>", lambda e: self.open_file())
        self.window.bind("<Control-s>", lambda e: self.save_file())
    
    def create_toolbar(self):
        toolbar = tk.Frame(self.window, relief=tk.RAISED, bd=1)
        toolbar.pack(side=tk.TOP, fill=tk.X)
        
        # Toolbar buttons
        new_btn = tk.Button(toolbar, text="New", command=self.new_file)
        new_btn.pack(side=tk.LEFT, padx=2, pady=2)
        
        open_btn = tk.Button(toolbar, text="Open", command=self.open_file)
        open_btn.pack(side=tk.LEFT, padx=2, pady=2)
        
        save_btn = tk.Button(toolbar, text="Save", command=self.save_file)
        save_btn.pack(side=tk.LEFT, padx=2, pady=2)
    
    def create_text_area(self):
        # Text area with scrollbars
        text_frame = tk.Frame(self.window)
        text_frame.pack(fill=tk.BOTH, expand=True)
        
        self.text_area = tk.Text(
            text_frame,
            wrap=tk.WORD,
            undo=True,
            font=("Consolas", 12)
        )
        
        scrollbar_y = tk.Scrollbar(text_frame, orient=tk.VERTICAL, command=self.text_area.yview)
        scrollbar_x = tk.Scrollbar(text_frame, orient=tk.HORIZONTAL, command=self.text_area.xview)
        
        self.text_area.config(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
        
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)
        scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)
        
        # Track changes
        self.text_area.bind("<KeyPress>", self.on_text_change)
        self.text_area.bind("<Button-1>", self.update_status)
        self.text_area.bind("<KeyRelease>", self.update_status)
    
    def create_status_bar(self):
        self.status_bar = tk.Label(
            self.window,
            text="Ready",
            relief=tk.SUNKEN,
            anchor=tk.W
        )
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
    
    def new_file(self):
        if self.check_save_changes():
            self.text_area.delete("1.0", tk.END)
            self.current_file = None
            self.is_modified = False
            self.update_title()
    
    def open_file(self):
        if self.check_save_changes():
            filename = filedialog.askopenfilename(
                title="Open File",
                filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
            )
            if filename:
                try:
                    with open(filename, 'r', encoding='utf-8') as file:
                        content = file.read()
                        self.text_area.delete("1.0", tk.END)
                        self.text_area.insert("1.0", content)
                        self.current_file = filename
                        self.is_modified = False
                        self.update_title()
                except Exception as e:
                    messagebox.showerror("Error", f"Failed to open file:\n{str(e)}")
    
    def save_file(self):
        if self.current_file:
            try:
                content = self.text_area.get("1.0", tk.END + "-1c")
                with open(self.current_file, 'w', encoding='utf-8') as file:
                    file.write(content)
                self.is_modified = False
                self.update_title()
                self.status_bar.config(text="File saved")
            except Exception as e:
                messagebox.showerror("Error", f"Failed to save file:\n{str(e)}")
        else:
            self.save_as_file()
    
    def save_as_file(self):
        filename = filedialog.asksaveasfilename(
            title="Save As",
            defaultextension=".txt",
            filetypes=[("Text files", "*.txt"), ("All files", "*.*")]
        )
        if filename:
            self.current_file = filename
            self.save_file()
    
    def check_save_changes(self):
        if self.is_modified:
            result = messagebox.askyesnocancel(
                "Save",
                "Document has been modified. Save changes?"
            )
            if result is True:
                self.save_file()
                return not self.is_modified
            elif result is False:
                return True
            else:
                return False
        return True
    
    def on_text_change(self, event=None):
        self.is_modified = True
        self.update_title()
        self.window.after_idle(self.update_status)
    
    def update_title(self):
        filename = self.current_file if self.current_file else "Untitled"
        modified = " *" if self.is_modified else ""
        self.window.title(f"{filename}{modified} - Text Editor")
    
    def update_status(self, event=None):
        # Cursor position
        cursor_pos = self.text_area.index(tk.INSERT)
        line, column = cursor_pos.split('.')
        
        # Word and character count
        content = self.text_area.get("1.0", tk.END + "-1c")
        word_count = len(content.split())
        char_count = len(content)
        
        status_text = f"Line: {line} | Column: {column} | Words: {word_count} | Chars: {char_count}"
        self.status_bar.config(text=status_text)
    
    def undo(self):
        try:
            self.text_area.edit_undo()
        except tk.TclError:
            pass
    
    def redo(self):
        try:
            self.text_area.edit_redo()
        except tk.TclError:
            pass
    
    def cut(self):
        try:
            self.text_area.event_generate("<<Cut>>")
        except tk.TclError:
            pass
    
    def copy(self):
        try:
            self.text_area.event_generate("<<Copy>>")
        except tk.TclError:
            pass
    
    def paste(self):
        try:
            self.text_area.event_generate("<<Paste>>")
        except tk.TclError:
            pass
    
    def on_closing(self):
        if self.check_save_changes():
            self.window.destroy()
    
    def run(self):
        self.window.mainloop()

# Run the editor
if __name__ == "__main__":
    editor = TextEditor()
    editor.run()

Frequently Asked Questions

How do I change a widget’s font?

widget.config(font=("Arial", 12, "bold"))
# or
custom_font = font.Font(family="Times", size=14, weight="normal")
widget.config(font=custom_font)

How can I disable a widget?

widget.config(state="disabled")
# To enable again
widget.config(state="normal")

How do I get a widget’s size?

width = widget.winfo_width()
height = widget.winfo_height()

How do I center a window on the screen?

def center_window(window, width, height):
    screen_width = window.winfo_screenwidth()
    screen_height = window.winfo_screenheight()
    
    x = (screen_width - width) // 2
    y = (screen_height - height) // 2
    
    window.geometry(f"{width}x{height}+{x}+{y}")

center_window(root, 800, 600)

How can I keep a window always on top?

window.attributes("-topmost", True)

How do I create a full‑screen application?

window.attributes("-fullscreen", True)
# Exit fullscreen
window.bind("<Escape>", lambda e: window.attributes("-fullscreen", False))

How do I add an icon to my application?

window.iconbitmap("path/to/icon.ico")  # Windows
# or
window.iconphoto(False, tk.PhotoImage(file="path/to/icon.png"))

How do I create a tooltip?

class ToolTip:
    def __init__(self, widget, text):
        self.widget = widget
        self.text = text
        self.tooltip = None
        self.widget.bind("<Enter>", self.show_tooltip)
        self.widget.bind("<Leave>", self.hide_tooltip)
    
    def show_tooltip(self, event=None):
        x, y, _, _ = self.widget.bbox("insert")
        x += self.widget.winfo_rootx() + 25
        y += self.widget.winfo_rooty() + 25
        
        self.tooltip = tk.Toplevel(self.widget)
        self.tooltip.wm_overrideredirect(True)
        self.tooltip.wm_geometry(f"+{x}+{y}")
        
        label = tk.Label(
            self.tooltip,
            text=self.text,
            background="yellow",
            relief="solid",
            borderwidth=1
        )
        label.pack()
    
    def hide_tooltip(self, event=None):
        if self.tooltip:
            self.tooltip.destroy()
            self.tooltip = None

# Usage
button = tk.Button(root, text="Button with tooltip")
ToolTip(button, "This is a tooltip")

Performance Optimization

Performance Tips

  1. Use after() instead of time.sleep():
def update_progress():
    # Update UI
    progress_bar['value'] += 1
    if progress_bar['value'] < 100:
        root.after(100, update_progress)  # instead of time.sleep(0.1)
  1. Group configuration updates:
# Inefficient
widget.config(text="New text")
widget.config(bg="red")
widget.config(font=("Arial", 12))

# Efficient
widget.config(text="New text", bg="red", font=("Arial", 12))
  1. Use StringVar for frequent updates:
text_var = tk.StringVar()
label = tk.Label(root, textvariable=text_var)
# Fast update without recreating the widget
text_var.set("New text")

Debugging and Testing

Key Debugging Techniques

# Get widget info
print(widget.winfo_class())      # widget class
print(widget.winfo_geometry())   # size and position
print(widget.winfo_children())   # child widgets
print(widget.config())           # all configuration options

# Event tracing
def debug_event(event):
    print(f"Event: {event.type}, Widget: {event.widget}")

root.bind_all("<Key>", debug_event)

Integration with Other Libraries

Using Matplotlib

import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np

def create_plot():
    fig, ax = plt.subplots(figsize=(8, 6))
    x = np.linspace(0, 10, 100)
    y = np.sin(x)
    ax.plot(x, y)
    ax.set_title("Plot of sin(x)")
    
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.draw()
    canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

root = tk.Tk()
root.title("Matplotlib in Tkinter")
create_plot()
root.mainloop()

Working with Databases

import sqlite3
from tkinter import ttk

class DatabaseApp:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("User Database")
        
        # Create database
        self.conn = sqlite3.connect("users.db")
        self.create_table()
        
        self.create_widgets()
    
    def create_table(self):
        cursor = self.conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                email TEXT NOT NULL,
                age INTEGER
            )
        """)
        self.conn.commit()
    
    def create_widgets(self):
        # Input form
        input_frame = tk.Frame(self.root)
        input_frame.pack(pady=10)
        
        tk.Label(input_frame, text="Name:").grid(row=0, column=0, padx=5)
        self.name_entry = tk.Entry(input_frame)
        self.name_entry.grid(row=0, column=1, padx=5)
        
        tk.Label(input_frame, text="Email:").grid(row=1, column=0, padx=5)
        self.email_entry = tk.Entry(input_frame)
        self.email_entry.grid(row=1, column=1, padx=5)
        
        tk.Label(input_frame, text="Age:").grid(row=2, column=0, padx=5)
        self.age_entry = tk.Entry(input_frame)
        self.age_entry.grid(row=2, column=1, padx=5)
        
        # Buttons
        button_frame = tk.Frame(self.root)
        button_frame.pack(pady=10)
        
        tk.Button(button_frame, text="Add", command=self.add_user).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="Refresh", command=self.refresh_list).pack(side=tk.LEFT, padx=5)
        tk.Button(button_frame, text="Delete", command=self.delete_user).pack(side=tk.LEFT, padx=5)
        
        # User table
        self.tree = ttk.Treeview(self.root, columns=("ID", "Name", "Email", "Age"), show="headings")
        self.tree.heading("ID", text="ID")
        self.tree.heading("Name", text="Name")
        self.tree.heading("Email", text="Email")
        self.tree.heading("Age", text="Age")
        self.tree.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        self.refresh_list()
    
    def add_user(self):
        name = self.name_entry.get()
        email = self.email_entry.get()
        age = self.age_entry.get()
        
        if name and email and age:
            cursor = self.conn.cursor()
            cursor.execute("INSERT INTO users (name, email, age) VALUES (?, ?, ?)", (name, email, int(age)))
            self.conn.commit()
            
            # Clear fields
            self.name_entry.delete(0, tk.END)
            self.email_entry.delete(0, tk.END)
            self.age_entry.delete(0, tk.END)
            
            self.refresh_list()
    
    def refresh_list(self):
        # Clear table
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # Load data
        cursor = self.conn.cursor()
        cursor.execute("SELECT * FROM users")
        for row in cursor.fetchall():
            self.tree.insert("", tk.END, values=row)
    
    def delete_user(self):
        selection = self.tree.selection()
        if selection:
            item = self.tree.item(selection[0])
            user_id = item['values'][0]
            
            cursor = self.conn.cursor()
            cursor.execute("DELETE FROM users WHERE id = ?", (user_id,))
            self.conn.commit()
            
            self.refresh_list()
    
    def run(self):
        self.root.mainloop()
        self.conn.close()

if __name__ == "__main__":
    app = DatabaseApp()
    app.run()

Deploying Applications

Creating an Executable with PyInstaller

# Install PyInstaller
pip install pyinstaller

# Build a one‑file executable
pyinstaller --onefile --windowed your_app.py

# With an icon
pyinstaller --onefile --windowed --icon=icon.ico your_app.py

# Include additional data files
pyinstaller --onefile --windowed --add-data "data;data" your_app.py

Project Structure for Distribution

my_tkinter_app/
├── main.py
├── requirements.txt
├── resources/
│   ├── icons/
│   └── images/
├── modules/
│   ├── __init__.py
│   ├── gui.py
│   └── logic.py
└── dist/
    └── (executable files)

Pros and Cons of Tkinter

Advantages

Easy to learn: Tkinter offers an intuitive API and extensive documentation, making it ideal for newcomers.

Built‑in: Comes with Python by default, requiring no extra dependencies.

Cross‑platform: Applications run unchanged on Windows, macOS and Linux.

Stable: Over 30 years of development have resulted in a very stable API.

Lightweight: Low system requirements and fast startup.

Integrates well: Works smoothly with other Python libraries.

Disadvantages

Limited visual capabilities: Provides a basic widget set without modern styling.

Outdated look: By default, apps may appear dated compared to newer GUI frameworks.

Restricted customization: Complex custom UI elements are hard to implement.

Performance constraints: Not suited for high‑intensity graphics or heavy‑load apps.

No mobile support: Cannot create native mobile applications.

Alternatives to Tkinter

PyQt / PySide

A more powerful and modern framework with rich features, but it requires separate installation and has a steeper learning curve.

Kivy

Specializes in multitouch applications and supports mobile platforms.

wxPython

Provides native look‑and‑feel on each platform.

Dear PyGui

A contemporary library offering high performance for tools and utilities.

Conclusion

Tkinter remains one of the most accessible and practical tools for building graphical interfaces in Python. Despite its limitations, the library is perfect for learning GUI programming, creating internal tools, automation utilities, and rapid prototyping.

Its simplicity, lack of external dependencies, and extensive documentation make Tkinter a top choice for beginner developers and projects where development speed matters more than cutting‑edge UI design.

For serious commercial applications that demand a modern look, consider more advanced alternatives, but Tkinter will always be a reliable component in a Python developer’s toolbox for a wide range of desktop‑application tasks.

News