Criando interfaces Tkinter visualmente com geração de código Python e temas modernos

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.

Tags: Tkinter ttkbootstrap pyinstaller gui-design python-gui

Publicado em 7-4 17:27