Curso de Python com Tkinter para Criação de Interfaces
Criando Menus e Barras de Ferramentas
Aprenda sobre criando menus e barras de ferramentas
Criando Menus e Barras de Ferramentas com Tkinter
Olá, futuro desenvolvedor de GUIs! 👋 Nesta aula prática, vamos mergulhar na criação de elementos essenciais para qualquer aplicação de desktop robusta: menus e barras de ferramentas. Eles não apenas tornam seu aplicativo mais profissional, mas também melhoram significativamente a experiência do usuário, oferecendo acesso rápido e organizado às funcionalidades.
Vamos aprender a construir menus de topo, submenus, menus de contexto e como criar barras de ferramentas personalizadas usando os recursos flexíveis do Tkinter. Prepare-se para tornar suas interfaces mais interativas e completas! 🚀
1. Introdução aos Menus e Barras de Ferramentas
Menus e barras de ferramentas são componentes cruciais para a usabilidade de qualquer aplicação gráfica.
- Menus: Geralmente localizados na parte superior da janela, eles fornecem uma lista hierárquica de comandos e opções. Pense nos menus "Arquivo", "Editar", "Exibir" que você encontra em quase todos os programas. O Tkinter oferece o widget
tkinter.Menupara essa finalidade. - Barras de Ferramentas: São coleções de botões (muitas vezes com ícones) que dão acesso rápido às funcionalidades mais usadas do aplicativo. Embora o Tkinter não tenha um widget
Toolbardedicado, podemos construí-las facilmente usando umtkinter.Framee populando-o com botões e outros widgets.
Nesta aula, focaremos em:
- Criar barras de menu principais.
- Adicionar submenus e separadores.
- Implementar itens de menu com comandos, caixas de seleção e botões de rádio.
- Construir menus de contexto (pop-up).
- Desenvolver barras de ferramentas personalizadas.
- Integrar menus e barras de ferramentas para funcionalidades compartilhadas.
Vamos começar! 🛠️
2. Criando Menus com tkinter.Menu
O widget tkinter.Menu é o coração da criação de menus no Tkinter. Ele pode ser usado para criar a barra de menu principal da sua janela, submenus dentro dessa barra ou até mesmo menus de contexto independentes.
2.1. Barra de Menu Principal
Para criar uma barra de menu principal, você primeiro cria uma instância de tkinter.Menu e a associa à sua janela principal usando janela.config(menu=barra_menu).
Exemplo Básico:
import tkinter as tk
from tkinter import messagebox
def novo_arquivo():
messagebox.showinfo("Ação", "Novo arquivo criado!")
def abrir_arquivo():
messagebox.showinfo("Ação", "Abrir arquivo...")
def salvar_arquivo():
messagebox.showinfo("Ação", "Arquivo salvo!")
def sair_aplicacao():
if messagebox.askyesno("Sair", "Tem certeza que deseja sair?"):
janela.quit()
janela = tk.Tk()
janela.title("Aplicação com Menu Básico")
janela.geometry("400x300")
# 1. Criar a barra de menu principal
barra_menu = tk.Menu(janela)
janela.config(menu=barra_menu)
# 2. Criar um menu 'Arquivo'
menu_arquivo = tk.Menu(barra_menu, tearoff=0) # tearoff=0 remove a linha tracejada
barra_menu.add_cascade(label="Arquivo", menu=menu_arquivo)
# 3. Adicionar itens ao menu 'Arquivo'
menu_arquivo.add_command(label="Novo", command=novo_arquivo)
menu_arquivo.add_command(label="Abrir", command=abrir_arquivo)
menu_arquivo.add_command(label="Salvar", command=salvar_arquivo)
menu_arquivo.add_separator() # Adiciona um separador visual
menu_arquivo.add_command(label="Sair", command=sair_aplicacao)
# 4. Criar um menu 'Ajuda'
menu_ajuda = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Ajuda", menu=menu_ajuda)
menu_ajuda.add_command(label="Sobre", command=lambda: messagebox.showinfo("Sobre", "Aplicação de Exemplo com Tkinter"))
tk.Label(janela, text="Explore o menu acima!").pack(pady=50)
janela.mainloop()2.2. Submenus e Opções Avançadas
Podemos adicionar submenus (menus cascata), itens de menu com caixas de seleção (checkbuttons) e botões de rádio (radiobuttons), e até desabilitar itens.
add_cascade(): Usado para criar submenus.add_checkbutton(): Cria um item de menu que pode ser marcado ou desmarcado.add_radiobutton(): Cria um item de menu que faz parte de um grupo onde apenas um pode ser selecionado por vez.entryconfig(): Permite configurar um item de menu existente (por exemplo, desabilitar).
import tkinter as tk
from tkinter import messagebox
# Variáveis para os checkbuttons e radiobuttons
mostrar_status = tk.BooleanVar()
mostrar_status.set(True) # Valor inicial
tema_selecionado = tk.StringVar()
tema_selecionado.set("Claro") # Valor inicial
def acao_editar(item):
messagebox.showinfo("Ação", f"Opção de edição: {item}")
def alternar_status():
messagebox.showinfo("Configuração", f"Mostrar barra de status: {mostrar_status.get()}")
def mudar_tema():
messagebox.showinfo("Configuração", f"Tema selecionado: {tema_selecionado.get()}")
janela = tk.Tk()
janela.title("Menus Avançados")
janela.geometry("500x350")
barra_menu = tk.Menu(janela)
janela.config(menu=barra_menu)
# Menu Arquivo (reutilizado do exemplo anterior)
menu_arquivo = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Arquivo", menu=menu_arquivo)
menu_arquivo.add_command(label="Novo", command=lambda: acao_editar("Novo"))
menu_arquivo.add_command(label="Abrir", command=lambda: acao_editar("Abrir"))
menu_arquivo.add_command(label="Salvar", command=lambda: acao_editar("Salvar"))
menu_arquivo.add_separator()
menu_arquivo.add_command(label="Sair", command=janela.quit)
# Menu Editar
menu_editar = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Editar", menu=menu_editar)
menu_editar.add_command(label="Cortar", command=lambda: acao_editar("Cortar"))
menu_editar.add_command(label="Copiar", command=lambda: acao_editar("Copiar"))
menu_editar.add_command(label="Colar", command=lambda: acao_editar("Colar"))
menu_editar.add_separator()
# Desabilitar um item
menu_editar.add_command(label="Excluir", command=lambda: acao_editar("Excluir"))
menu_editar.entryconfig("Excluir", state="disabled") # Desabilita o item "Excluir"
# Menu Exibir (com checkbutton e submenu)
menu_exibir = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Exibir", menu=menu_exibir)
menu_exibir.add_checkbutton(label="Barra de Status",
variable=mostrar_status,
command=alternar_status)
# Submenu 'Tema'
menu_tema = tk.Menu(menu_exibir, tearoff=0)
menu_exibir.add_cascade(label="Tema", menu=menu_tema)
menu_tema.add_radiobutton(label="Claro",
variable=tema_selecionado,
value="Claro",
command=mudar_tema)
menu_tema.add_radiobutton(label="Escuro",
variable=tema_selecionado,
value="Escuro",
command=mudar_tema)
menu_tema.add_radiobutton(label="Sistema",
variable=tema_selecionado,
value="Sistema",
command=mudar_tema)
tk.Label(janela, text="Experimente os menus 'Editar' e 'Exibir'!").pack(pady=50)
janela.mainloop()2.3. Menus de Contexto (Pop-up)
Menus de contexto aparecem quando o usuário clica com o botão direito do mouse em um widget específico. Eles são criados da mesma forma que os menus normais, mas são exibidos usando o método post() em resposta a um evento.
import tkinter as tk
from tkinter import messagebox
def acao_contexto(item):
messagebox.showinfo("Menu de Contexto", f"Você clicou em: {item}")
janela = tk.Tk()
janela.title("Menu de Contexto")
janela.geometry("300x200")
# Criar o menu de contexto
menu_contexto = tk.Menu(janela, tearoff=0)
menu_contexto.add_command(label="Opção 1", command=lambda: acao_contexto("Opção 1"))
menu_contexto.add_command(label="Opção 2", command=lambda: acao_contexto("Opção 2"))
menu_contexto.add_separator()
menu_contexto.add_command(label="Fechar", command=janela.quit)
# Função para exibir o menu de contexto
def exibir_menu_contexto(event):
try:
menu_contexto.tk_popup(event.x_root, event.y_root)
finally:
menu_contexto.grab_release() # Libera o "grab" do mouse
# Associar o menu de contexto a um widget (aqui, a própria janela)
janela.bind("<Button-3>", exibir_menu_contexto) # <Button-3> é o botão direito do mouse
tk.Label(janela, text="Clique com o botão direito em qualquer lugar da janela!").pack(pady=50)
janela.mainloop()💡 Dica da Documentação Oficial: A documentação do Tkinter (e Python) para tkinter.Menu enfatiza o uso de tearoff=0 para evitar a "linha tracejada" que permite separar o menu da janela. Além disso, a forma correta de exibir um menu pop-up é usando tk_popup(x, y) e, em seguida, grab_release() para garantir que o menu seja fechado corretamente se o usuário clicar fora dele.
3. Criando Barras de Ferramentas Personalizadas
Como mencionado, o Tkinter não possui um widget Toolbar nativo. No entanto, podemos construir uma facilmente usando um tkinter.Frame como contêiner e adicionando tkinter.Button ou tkinter.Label (para ícones) dentro dele.
3.1. Barra de Ferramentas Simples com Botões de Texto
import tkinter as tk
from tkinter import messagebox
def acao_toolbar(nome_acao):
messagebox.showinfo("Barra de Ferramentas", f"Ação: {nome_acao}")
janela = tk.Tk()
janela.title("Barra de Ferramentas Simples")
janela.geometry("500x200")
# Criar um Frame para a barra de ferramentas
toolbar = tk.Frame(janela, bd=1, relief=tk.RAISED) # Borda e relevo para visual
toolbar.pack(side=tk.TOP, fill=tk.X) # Ancorar no topo e preencher horizontalmente
# Adicionar botões à barra de ferramentas
btn_novo = tk.Button(toolbar, text="Novo", command=lambda: acao_toolbar("Novo"))
btn_novo.pack(side=tk.LEFT, padx=2, pady=2)
btn_abrir = tk.Button(toolbar, text="Abrir", command=lambda: acao_toolbar("Abrir"))
btn_abrir.pack(side=tk.LEFT, padx=2, pady=2)
btn_salvar = tk.Button(toolbar, text="Salvar", command=lambda: acao_toolbar("Salvar"))
btn_salvar.pack(side=tk.LEFT, padx=2, pady=2)
# Adicionar um separador visual (pode ser um Label com cor de fundo ou um Frame pequeno)
separador = tk.Frame(toolbar, width=2, bd=1, relief=tk.SUNKEN)
separador.pack(side=tk.LEFT, padx=5, pady=2, fill=tk.Y)
btn_ajuda = tk.Button(toolbar, text="Ajuda", command=lambda: acao_toolbar("Ajuda"))
btn_ajuda.pack(side=tk.LEFT, padx=2, pady=2)
tk.Label(janela, text="Clique nos botões da barra de ferramentas!").pack(pady=50)
janela.mainloop()3.2. Barra de Ferramentas com Ícones (usando PhotoImage)
Para ícones simples, podemos usar tkinter.PhotoImage. Para formatos mais complexos (como PNG, JPG), você precisará da biblioteca Pillow (PIL Fork). Para simplificar, usaremos um ícone embutido ou um ícone GIF/PPM se você tiver um.
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk # Necessário instalar: pip install Pillow
def acao_toolbar(nome_acao):
messagebox.showinfo("Barra de Ferramentas", f"Ação: {nome_acao}")
janela = tk.Tk()
janela.title("Barra de Ferramentas com Ícones")
janela.geometry("500x200")
# --- Carregar Ícones ---
# Para ícones PNG/JPG, você precisa da biblioteca Pillow
# Exemplo: Tente carregar um ícone de um arquivo
try:
# Substitua 'icon_new.png' pelo caminho de um ícone real no seu sistema
# Ou crie um pequeno arquivo PNG/GIF para teste.
# Ex: crie um arquivo 'new.png' de 16x16 pixels.
original_image_new = Image.open("icons/new.png") # Caminho para o seu ícone
icon_new = ImageTk.PhotoImage(original_image_new.resize((16, 16))) # Redimensionar se necessário
original_image_open = Image.open("icons/open.png") # Caminho para o seu ícone
icon_open = ImageTk.PhotoImage(original_image_open.resize((16, 16)))
original_image_save = Image.open("icons/save.png") # Caminho para o seu ícone
icon_save = ImageTk.PhotoImage(original_image_save.resize((16, 16)))
except FileNotFoundError:
messagebox.showerror("Erro de Ícone", "Não foi possível carregar os ícones. Certifique-se de que 'icons/new.png', 'icons/open.png', 'icons/save.png' existem. Usando texto.")
icon_new = None
icon_open = None
icon_save = None
except Exception as e:
messagebox.showerror("Erro de Ícone", f"Erro ao carregar ícones: {e}. Usando texto.")
icon_new = None
icon_open = None
icon_save = None
# --- Barra de Ferramentas ---
toolbar = tk.Frame(janela, bd=1, relief=tk.RAISED)
toolbar.pack(side=tk.TOP, fill=tk.X)
# Função auxiliar para criar botões na toolbar
def criar_botao_toolbar(parent, text, image, command):
if image:
btn = tk.Button(parent, image=image, command=command)
else:
btn = tk.Button(parent, text=text, command=command)
btn.pack(side=tk.LEFT, padx=2, pady=2)
return btn
criar_botao_toolbar(toolbar, "Novo", icon_new, lambda: acao_toolbar("Novo"))
criar_botao_toolbar(toolbar, "Abrir", icon_open, lambda: acao_toolbar("Abrir"))
criar_botao_toolbar(toolbar, "Salvar", icon_save, lambda: acao_toolbar("Salvar"))
tk.Label(janela, text="Barra de ferramentas com ícones (ou texto se ícones não carregarem)").pack(pady=50)
janela.mainloop()👉 Observação sobre Ícones: Para este exemplo funcionar com ícones, você precisa ter a biblioteca Pillow instalada (pip install Pillow) e ter arquivos de imagem (.png, .gif, etc.) nos caminhos especificados (ex: icons/new.png). Se você não tiver ícones, o código fará fallback para botões de texto.
4. Integração: Menus e Barras de Ferramentas Compartilhando Funcionalidades
A beleza de menus e barras de ferramentas é que eles geralmente oferecem acesso às mesmas funcionalidades. É uma boa prática definir as ações em funções separadas e depois vinculá-las tanto aos itens do menu quanto aos botões da barra de ferramentas.
import tkinter as tk
from tkinter import messagebox
from PIL import Image, ImageTk # pip install Pillow
class AplicacaoCompleta:
def __init__(self, master):
self.master = master
master.title("Aplicação Integrada")
master.geometry("600x400")
self.criar_acoes()
self.criar_menu_bar()
self.criar_toolbar()
self.criar_conteudo_principal()
def criar_acoes(self):
# Funções que serão chamadas pelos menus e toolbar
self.acoes = {
"novo": lambda: messagebox.showinfo("Ação", "Novo arquivo criado!"),
"abrir": lambda: messagebox.showinfo("Ação", "Abrir arquivo..."),
"salvar": lambda: messagebox.showinfo("Ação", "Arquivo salvo!"),
"cortar": lambda: messagebox.showinfo("Ação", "Cortar texto!"),
"copiar": lambda: messagebox.showinfo("Ação", "Copiar texto!"),
"colar": lambda: messagebox.showinfo("Ação", "Colar texto!"),
"sobre": lambda: messagebox.showinfo("Sobre", "Aplicação Integrada Tkinter v1.0"),
"sair": self.master.quit
}
def criar_menu_bar(self):
barra_menu = tk.Menu(self.master)
self.master.config(menu=barra_menu)
# Menu Arquivo
menu_arquivo = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Arquivo", menu=menu_arquivo)
menu_arquivo.add_command(label="Novo", command=self.acoes["novo"])
menu_arquivo.add_command(label="Abrir", command=self.acoes["abrir"])
menu_arquivo.add_command(label="Salvar", command=self.acoes["salvar"])
menu_arquivo.add_separator()
menu_arquivo.add_command(label="Sair", command=self.acoes["sair"])
# Menu Editar
menu_editar = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Editar", menu=menu_editar)
menu_editar.add_command(label="Cortar", command=self.acoes["cortar"])
menu_editar.add_command(label="Copiar", command=self.acoes["copiar"])
menu_editar.add_command(label="Colar", command=self.acoes["colar"])
# Menu Ajuda
menu_ajuda = tk.Menu(barra_menu, tearoff=0)
barra_menu.add_cascade(label="Ajuda", menu=menu_ajuda)
menu_ajuda.add_command(label="Sobre", command=self.acoes["sobre"])
def criar_toolbar(self):
self.toolbar_frame = tk.Frame(self.master, bd=1, relief=tk.RAISED)
self.toolbar_frame.pack(side=tk.TOP, fill=tk.X)
# --- Carregar Ícones (tentativa) ---
self.icons = {}
try:
# Assumindo que você tem ícones 16x16px em uma pasta 'icons/'
self.icons["new"] = ImageTk.PhotoImage(Image.open("icons/new.png").resize((16, 16)))
self.icons["open"] = ImageTk.PhotoImage(Image.open("icons/open.png").resize((16, 16)))
self.icons["save"] = ImageTk.PhotoImage(Image.open("icons/save.png").resize((16, 16)))
self.icons["cut"] = ImageTk.PhotoImage(Image.open("icons/cut.png").resize((16, 16)))
self.icons["copy"] = ImageTk.PhotoImage(Image.open("icons/copy.png").resize((16, 16)))
self.icons["paste"] = ImageTk.PhotoImage(Image.open("icons/paste.png").resize((16, 16)))
except FileNotFoundError:
messagebox.showwarning("Ícones Ausentes", "Ícones não encontrados. A barra de ferramentas usará texto.")
self.icons = {} # Limpa para usar texto
except Exception as e:
messagebox.showwarning("Erro de Ícone", f"Erro ao carregar ícones: {e}. Usando texto.")
self.icons = {}
# Função auxiliar para criar botões na toolbar
def add_toolbar_button(text, icon_key, command):
if icon_key in self.icons:
btn = tk.Button(self.toolbar_frame, image=self.icons[icon_key], command=command)
else:
btn = tk.Button(self.toolbar_frame, text=text, command=command)
btn.pack(side=tk.LEFT, padx=2, pady=2)
add_toolbar_button("Novo", "new", self.acoes["novo"])
add_toolbar_button("Abrir", "open", self.acoes["abrir"])
add_toolbar_button("Salvar", "save", self.acoes["salvar"])
tk.Frame(self.toolbar_frame, width=2, bd=1, relief=tk.SUNKEN).pack(side=tk.LEFT, padx=5, pady=2, fill=tk.Y)
add_toolbar_button("Cortar", "cut", self.acoes["cortar"])
add_toolbar_button("Copiar", "copy", self.acoes["copiar"])
add_toolbar_button("Colar", "paste", self.acoes["colar"])
def criar_conteudo_principal(self):
self.texto = tk.Text(self.master, wrap=tk.WORD, undo=True)
self.texto.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
self.texto.insert(tk.END, "Este é o corpo principal da sua aplicação.\n")
self.texto.insert(tk.END, "Experimente os menus e a barra de ferramentas!")
if __name__ == "__main__":
root = tk.Tk()
app = AplicacaoCompleta(root)
root.mainloop()
Neste exemplo, as ações (novo, abrir, salvar, etc.) são definidas uma única vez e referenciadas tanto pelos itens de menu quanto pelos botões da barra de ferramentas. Isso garante consistência e facilita a manutenção do código.
5. Exercícios e Desafios 🚀
Agora é a sua vez de colocar a mão na massa! Crie uma aplicação Tkinter que simule um editor de texto simples, incorporando menus e uma barra de ferramentas.
Tarefas:
- Crie uma janela principal com o título "Meu Editor Tkinter".
- Implemente uma barra de menu principal com os seguintes menus:
- Arquivo:
- "Novo" (limpa a área de texto)
- "Abrir" (exibe uma caixa de diálogo
filedialog.askopenfilenamee carrega o conteúdo para a área de texto) - "Salvar" (exibe uma caixa de diálogo
filedialog.asksaveasfilenamee salva o conteúdo da área de texto) - Separador
- "Sair" (fecha a aplicação)
- Editar:
- "Cortar" (corta o texto selecionado)
- "Copiar" (copia o texto selecionado)
- "Colar" (cola o texto)
- Separador
- "Desfazer" (desfaz a última ação no
Textwidget) - "Refazer" (refaz a última ação no
Textwidget)
- Exibir:
- "Barra de Status" (um
Checkbuttonde menu que alterna a visibilidade de uma barra de status na parte inferior da janela. Use umatk.BooleanVar.) - Separador
- Submenu "Zoom":
- "Normal (100%)" (um
Radiobuttonde menu) - "Ampliar (150%)" (um
Radiobuttonde menu) - "Reduzir (75%)" (um
Radiobuttonde menu) (Para simplificar, as ações de zoom podem apenas mostrar ummessagebox.showinfo.)
- "Normal (100%)" (um
- "Barra de Status" (um
- Arquivo:
- Crie uma barra de ferramentas abaixo da barra de menu com botões para as ações "Novo", "Abrir", "Salvar", "Cortar", "Copiar", "Colar".
- Tente usar ícones para os botões da barra de ferramentas (se não tiver, use texto). Lembre-se de instalar
Pillowse usar PNG/JPG.
- Tente usar ícones para os botões da barra de ferramentas (se não tiver, use texto). Lembre-se de instalar
- Inclua uma área de texto (
tk.Text) que ocupe a maior parte da janela e permita edição. - Adicione uma barra de status (
tk.Label) na parte inferior da janela que possa ser ocultada/exibida pelo menu "Exibir". - Implemente um menu de contexto (clique direito) na área de texto com as opções "Cortar", "Copiar", "Colar".
Este é um projeto mais completo, então reserve um tempo para cada parte. Boa sorte! 💪
6. Resumo e Próximos Passos
Nesta aula, exploramos a criação de menus e barras de ferramentas, componentes vitais para a interatividade e usabilidade de aplicações Tkinter:
- Aprendemos a criar barras de menu principais usando
tkinter.Menuejanela.config(menu=...). - Adicionamos itens de menu com
add_command(),add_separator(),add_checkbutton(),add_radiobutton()eadd_cascade()para submenus. - Implementamos menus de contexto (pop-up) que aparecem em resposta a eventos do mouse.
- Construímos barras de ferramentas personalizadas utilizando
tkinter.Framecomo contêiner etkinter.Buttonpara as ações. - Vimos como integrar menus e barras de ferramentas, compartilhando as mesmas funções de ação para manter a consistência e a organização do código.
Com essas habilidades, suas interfaces Tkinter já podem parecer e funcionar como aplicativos de desktop muito mais completos!
Próximos Passos:
No próximo módulo, vamos aprofundar em tópicos como:
- Diálogos e Caixas de Mensagem mais avançadas.
- Trabalhando com eventos e bindings de teclado.
- Widgets personalizados e técnicas de layout avançadas.
Continue praticando e explorando as possibilidades do Tkinter! Até a próxima aula! 👋