Interfaces Gráficas com Tkinter

Laboratório de Programação — Ciência da Computação

Tkinter, widgets, layouts, eventos e boas práticas — com syntax highlighting

O que é Tkinter?

  • Toolkit GUI nativo do Python, baseado em Tcl/Tk.
  • Multiplataforma (Linux, macOS, Windows) e geralmente já instalado.
  • Ideal para criar apps com botões, entradas, diálogos, menus, etc.

Teste rápido no terminal: python -m tkinter (abre uma janela demo).

Primeira janela

import tkinter as tk

root = tk.Tk()
root.title("Minha Aplicação")
root.geometry("500x300")  # LxA
root.mainloop()

Conceitos

  • root: janela principal (loop de eventos).
  • widget: elemento da UI (Label, Button, Entry…).
  • layout: pack, grid, place.

Widgets Essenciais

  • Label: texto estático
  • Button: aciona comandos
  • Entry: entrada de 1 linha
  • Checkbutton, Radiobutton
  • Text / ScrolledText
  • Listbox, Combobox
  • Frame: container/agrupador
  • Menu, Menubar
  • ttk: versões temáticas

Label, Entry e Button

import tkinter as tk

def exibir_texto():
    texto = entrada.get()
    rotulo_resultado.config(text=f"Você digitou: {texto}")

root = tk.Tk()
tk.Label(root, text="Digite algo:").pack()
entrada = tk.Entry(root)
entrada.pack()
tk.Button(root, text="Exibir", command=exibir_texto).pack()
rotulo_resultado = tk.Label(root, text="")
rotulo_resultado.pack()
root.mainloop()

Messagebox & Filedialog

import tkinter as tk
from tkinter import messagebox, filedialog

root = tk.Tk()

def abrir_arquivo():
    caminho = filedialog.askopenfilename(
        title="Abrir arquivo",
        filetypes=[("Texto", "*.txt"), ("Todos", "*.*")]
    )
    if caminho:
        messagebox.showinfo("Selecionado", caminho)

tk.Button(root, text="Abrir arquivo", command=abrir_arquivo).pack(pady=8)
root.mainloop()

Gerenciadores de Layout

  • pack: empilha widgets (top/bottom/left/right, fill, expand).
  • grid: posiciona em linhas/colunas (row/column/rowspan/columnspan).
  • place: coordenadas absolutas/relativas (x, y, relx, rely, relwidth…).

Exemplo com grid

import tkinter as tk

root = tk.Tk()
root.title("Grid")

tk.Label(root, text="Usuário").grid(row=0, column=0, sticky="e")
tk.Entry(root).grid(row=0, column=1, padx=6, pady=4)

tk.Label(root, text="Senha").grid(row=1, column=0, sticky="e")
tk.Entry(root, show="*").grid(row=1, column=1, padx=6, pady=4)

tk.Button(root, text="Entrar").grid(row=2, column=0, columnspan=2, pady=8)
root.mainloop()

Exemplo com place

import tkinter as tk

root = tk.Tk()
root.geometry("300x200")

tk.Label(root, text="Widget 1", bg="#ff9999").place(x=20, y=20)
tk.Label(root, text="Widget 2", bg="#99ff99").place(x=100, y=80)
tk.Label(root, text="Widget 3", bg="#9999ff").place(x=200, y=140)

root.mainloop()

Eventos & Callbacks

import tkinter as tk
from tkinter import messagebox

def ao_clicar():
    messagebox.showinfo("Mensagem", "Você clicou!")

root = tk.Tk()
btn = tk.Button(root, text="Clique aqui", command=ao_clicar)
btn.pack(padx=10, pady=10)

# Atalho de teclado: Enter chama o botão
root.bind("<Return>", lambda e: ao_clicar())
root.mainloop()

Atualizando a UI

  • Não bloqueie o loop principal com tarefas longas.
  • Use after(ms, func) para agendar atualizações.
  • Para I/O pesado, considere threading + queue + after.
import tkinter as tk

root = tk.Tk()
contador = tk.IntVar(value=0)

def tick():
    contador.set(contador.get() + 1)
    root.after(1000, tick)  # chama novamente em 1s

tk.Label(root, textvariable=contador).pack(pady=10)
root.after(1000, tick)
root.mainloop()

ScrolledText & Frames

import tkinter as tk
from tkinter.scrolledtext import ScrolledText

root = tk.Tk()

frame = tk.Frame(root, padx=8, pady=8)
frame.pack(fill="both", expand=True)

tk.Label(frame, text="Log:").pack(anchor="w")
log = ScrolledText(frame, height=8, width=40)
log.pack(fill="both", expand=True)

log.insert("end", "Linha 1\nLinha 2\n")
root.mainloop()

Menu de Aplicação

import tkinter as tk
from tkinter import messagebox

root = tk.Tk()
menubar = tk.Menu(root)

def sobre():
    messagebox.showinfo("Sobre", "Demo Tkinter")

menu_arq = tk.Menu(menubar, tearoff=0)
menu_arq.add_command(label="Sair", command=root.quit)
menubar.add_cascade(label="Arquivo", menu=menu_arq)

menu_ajuda = tk.Menu(menubar, tearoff=0)
menu_ajuda.add_command(label="Sobre", command=sobre)
menubar.add_cascade(label="Ajuda", menu=menu_ajuda)

root.config(menu=menubar)
root.mainloop()

ttk — Widgets Tematizados

  • Conjunto de widgets com aparência nativa do SO.
  • Ex.: ttk.Button, ttk.Entry, ttk.Combobox, ttk.Treeview.
  • Suporte a temas via ttk.Style().
import tkinter as tk
from tkinter import ttk

root = tk.Tk()
style = ttk.Style(root)
print(style.theme_names())  # temas disponíveis
style.theme_use("clam")     # ou "default", "alt", etc.

ttk.Label(root, text="Nome:").grid(row=0, column=0, padx=6, pady=6)
ttk.Entry(root).grid(row=0, column=1, padx=6, pady=6)
ttk.Button(root, text="OK").grid(row=1, column=0, columnspan=2, pady=8)
root.mainloop()

Treeview (tabela básica)

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
cols = ("ID", "Nome", "Nota")
tv = ttk.Treeview(root, columns=cols, show="headings", height=5)
for c in cols:
    tv.heading(c, text=c)
    tv.column(c, width=100)
tv.pack(fill="both", expand=True)

# inserir linhas
tv.insert("", "end", values=(1, "Ana", 9.1))
tv.insert("", "end", values=(2, "João", 7.5))
root.mainloop()

Estruturando o App com Classes

Separa lógica e interface; facilita manutenção e testes.

import tkinter as tk
from tkinter import ttk, messagebox

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Agenda Simples")
        self.geometry("360x240")
        self._build_ui()

    def _build_ui(self):
        ttk.Label(self, text="Nome:").grid(row=0, column=0, padx=6, pady=6, sticky="e")
        self.nome = ttk.Entry(self)
        self.nome.grid(row=0, column=1, padx=6, pady=6)

        ttk.Label(self, text="Telefone:").grid(row=1, column=0, padx=6, pady=6, sticky="e")
        self.tel = ttk.Entry(self)
        self.tel.grid(row=1, column=1, padx=6, pady=6)

        ttk.Button(self, text="Salvar", command=self.salvar).grid(row=2, column=0, columnspan=2, pady=8)

    def salvar(self):
        messagebox.showinfo("OK", f"{self.nome.get()} — {self.tel.get()}")

if __name__ == "__main__":
    App().mainloop()

Mind Map (Tkinter)

Mind map Tkinter

Podcast

A Essência do Tkinter — Interfaces Gráficas em Python

Boas Práticas

  • Evite lógica pesada no thread principal; use after ou threads.
  • Organize widgets em Frames e separe camadas (UI vs lógica).
  • Use ttk para aparência consistente e temas.
  • Valide entradas do usuário; trate exceções (ex.: dialogs).

Checklist Rápido

  • Título/Geometria definidos.
  • Layout com grid/pack consistente.
  • Eventos conectados a callbacks.
  • Feedback via messagebox/status.

Exercícios (Lab)

  1. Crie um formulário (Nome, Email, Curso) com ttk e valide campos.
  2. Implemente um menu “Arquivo → Abrir” para carregar um texto e exibir em ScrolledText.
  3. Crie uma calculadora simples (grid), teclas & teclado (bind).
  4. Adicione uma barra de status atualizada via after.

Conclusões

  • Tkinter é prático, nativo e suficiente para muitas GUIs desktop.
  • Domine widgets essenciais, layouts e eventos.
  • Estruture seu app com classes e use ttk para uma UI mais moderna.