O desenvolvimento de interfaces desktop em Python pode ser acelerado com assistentes de layout que permitem montar telas de forma visual e exportar o código correspondente. Essa abordagem separa a responsabilidade da construção da interface da lógica de evenntos, facilitando a manutenção e a evolução do projeto.
Estrutura típica do código gerado
Ferramentas de design visual costumam gerar duas classses principais: uma que representa a interface e outra que herda da primeira para tratar os eventos. Abaixo, um exemplo simplificado dessa organização, com nomes e estrutura diferentes do padrão original.
import tkinter as tk
from tkinter import ttk, messagebox
from typing import Dict
class AplicativoBase(tk.Tk):
componentes: Dict[str, tk.Widget] = {}
def __init__(self):
super().__init__()
self._configurar_janela()
self._criar_widgets()
def _configurar_janela(self):
self.title("Editor Visual Tkinter")
largura, altura = 680, 440
x = (self.winfo_screenwidth() - largura) // 2
y = (self.winfo_screenheight() - altura) // 2
self.geometry(f"{largura}x{altura}+{x}+{y}")
self.resizable(False, False)
def _criar_widgets(self):
self.componentes["lbl_usuario"] = tk.Label(self, text="Usuário:")
self.componentes["lbl_usuario"].place(x=50, y=40, width=80, height=25)
self.componentes["ent_usuario"] = tk.Entry(self)
self.componentes["ent_usuario"].place(x=140, y=40, width=220, height=25)
self.componentes["ent_usuario"].insert(0, "digite aqui")
self.componentes["btn_enviar"] = ttk.Button(self, text="Enviar")
self.componentes["btn_enviar"].place(x=380, y=40, width=90, height=28)
class Aplicativo(AplicativoBase):
def __init__(self):
super().__init__()
self._vincular_eventos()
def _vincular_eventos(self):
self.componentes["btn_enviar"].bind("<Button>", self._ao_clicar)
def _ao_clicar(self, evento):
texto = self.componentes["ent_usuario"].get()
messagebox.showinfo("Informação", f"Valor digitado: {texto}")
if __name__ == "__main__":
Aplicativo().mainloop()
Personalizando o visual com ttkbootstrap
Após gerar a estrutura base, é possível aplicar temas modernos com a biblioteca ttkbootstrap. Ela oferece dezenas de variações, como morph, darkly, flatly e cyborg, que podem ser ativadas em uma única linha.
import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb
class App(tb.Window):
def __init__(self):
super().__init__(themename="morph")
self.title("Formulário Moderno")
self.geometry("400x300")
self._construir_interface()
def _construir_interface(self):
ttk.Label(self, text="Nome completo:").pack(pady=(20, 5))
self.campo_nome = ttk.Entry(self, width=40)
self.campo_nome.pack(pady=5)
ttk.Label(self, text="E-mail:").pack(pady=(10, 5))
self.campo_email = ttk.Entry(self, width=40)
self.campo_email.pack(pady=5)
ttk.Button(
self,
text="Confirmar",
command=self._confirmar,
bootstyle="success"
).pack(pady=20)
def _confirmar(self):
print(f"Nome: {self.campo_nome.get()}")
print(f"E-mail: {self.campo_email.get()}")
if __name__ == "__main__":
App().mainloop()
Gerenciando múltiplas janelas
Em aplicações maiores, é comum controlar janelas secundárias programaticamente. O exemplo a seguir demonstra como abrir, exibir, ocultar e fechar uma segunda janela usando Tkinter puro com tema do ttkbootstrap.
import tkinter as tk
from tkinter import ttk
import ttkbootstrap as tb
def abrir_secundaria():
global janela_sec
janela_sec = tk.Toplevel(root)
janela_sec.title("Janela Secundária")
janela_sec.geometry("400x300")
def exibir_secundaria():
janela_sec.deiconify()
def ocultar_secundaria():
janela_sec.withdraw()
def fechar_secundaria():
janela_sec.destroy()
root = tb.Window(themename="morph")
root.title("Janela Principal")
root.geometry("350x250")
ttk.Button(root, text="Abrir janela", command=abrir_secundaria).pack(pady=10)
ttk.Button(root, text="Exibir janela", command=exibir_secundaria).pack(pady=10)
ttk.Button(root, text="Ocultar janela", command=ocultar_secundaria).pack(pady=10)
ttk.Button(root, text="Fechar janela", command=fechar_secundaria).pack(pady=10)
root.mainloop()
Empacotando a aplicação com PyInstaller
Para distribuir o aplicativo como um executável único, o PyInstaller deve incluir os recursos do ttkbootstrap. Caso contrário, os temas podem não ser encontrados durante a execução do binário.
pyinstaller --onefile --windowed app.py --collect-all ttkbootstrap
Com esse comando, todos os arquivos de tema são copiados para dentro do executável, evitando erros de caminho ao carregar os estilos.