Bibliotecas Gráficas
Modulo TKinter
O módulo tkinter é a biblioteca padrão do Python para criar interfaces gráficas (GUI). Ele é um wrapper para a biblioteca Tk, que fornece elementos visuais como botões, rótulos, caixas de entrada e janelas.
O Packer (pack) é um gerenciador de layout do tkinter que organiza widgets automaticamente dentro de uma janela. Ele posiciona os elementos em relação ao espaço disponível e ao que já foi adicionado.
pack() vs grid() vs place()
pack()→ Simples e empilha widgets automaticamente.grid()→ Usa uma grade (linhas e colunas) para organizar widgets.place()→ Posiciona os widgets de forma exata (coordenadasx, y).
Não é possivel misturar grid e pack no mesmo layout.
import tkinter
# Define uma tupla da fonte, tamanho e estilo da fonte
FONT = ("Arial", 24, "bold")
windows = tkinter.Tk()
windows.title("My GUI Test")
windows.minsize(width=500, height=300)
windows.config(padx=20, pady=20) # Padding das bordas da tela
# Cria um label
my_label = tkinter.Label(text="Hello, World!", font=FONT)
# Adiciona o label na janela com o packer
my_label.pack(side="right") # expand=true, ocupa todo espaço da tela
# Depois de criado posso configurar as propriedades pelo metodo config() ou pelo indice
my_label.config(text="Nova Janela")
my_label["background"] = "red"
def button_clicked():
# get() metodo que retorna a entrada em string
my_label["text"] = input.get()
# command recebe o nome de uma função de eventos
button = tkinter.Button(text="Click Here", command=button_clicked)
button.place(x=200, y=0)
# button.grid(column=0, row=0) # Só pode ser usado sozinho
input = tkinter.Entry(width=10)
input.place(x=0, y=0) # coordenadas exatas
# Metodo para manter a janela aberta e rodando
windows.mainloop()
Vários exemplos da classe tkinter
from tkinter import *
#Creating a new window and configurations
window = Tk()
window.title("Widget Examples")
window.minsize(width=500, height=500)
#Labels
label = Label(text="This is old text")
label.config(text="This is new text")
label.pack()
#Buttons
def action():
print("Do something")
#calls action() when pressed
button = Button(text="Click Me", command=action)
button.pack()
#Entries
entry = Entry(width=30)
#Add some text to begin with
entry.insert(END, string="Some text to begin with.")
#Gets text in entry
print(entry.get())
entry.pack()
#Text
text = Text(height=5, width=30)
#Puts cursor in textbox.
text.focus()
#Adds some text to begin with.
text.insert(END, "Example of multi-line text entry.")
#Get's current value in textbox at line 1, character 0
print(text.get("1.0", END))
text.pack()
#Spinbox
def spinbox_used():
#gets the current value in spinbox.
print(spinbox.get())
spinbox = Spinbox(from_=0, to=10, width=5, command=spinbox_used)
spinbox.pack()
#Scale
#Called with current scale value.
def scale_used(value):
print(value)
scale = Scale(from_=0, to=100, command=scale_used)
scale.pack()
#Checkbutton
def checkbutton_used():
#Prints 1 if On button checked, otherwise 0.
print(checked_state.get())
#variable to hold on to checked state, 0 is off, 1 is on.
checked_state = IntVar()
checkbutton = Checkbutton(text="Is On?", variable=checked_state, command=checkbutton_used)
checked_state.get()
checkbutton.pack()
#Radiobutton
def radio_used():
print(radio_state.get())
#Variable to hold on to which radio button value is checked.
radio_state = IntVar()
radiobutton1 = Radiobutton(text="Option1", value=1, variable=radio_state, command=radio_used)
radiobutton2 = Radiobutton(text="Option2", value=2, variable=radio_state, command=radio_used)
radiobutton1.pack()
radiobutton2.pack()
#Listbox
def listbox_used(event):
# Gets current selection from listbox
print(listbox.get(listbox.curselection()))
listbox = Listbox(height=4)
fruits = ["Apple", "Pear", "Orange", "Banana"]
for item in fruits:
listbox.insert(fruits.index(item), item)
listbox.bind("<<ListboxSelect>>", listbox_used)
listbox.pack()
window.mainloop()
from tkinter import *
from tkinter import messagebox
from random import shuffle, randint, choice
import json
# ------ GENERATOR PASS ------- #
def generate_password():
letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']
password_letters = [choice(letters) for _ in range(randint(8, 10))]
password_symbols = [choice(symbols) for _ in range(randint(2, 4))]
password_numbers = [choice(numbers)for _ in range(randint(2, 4))]
password_list = password_letters + password_symbols + password_numbers
shuffle(password_list)
# junta todos os elementos da lista e retorna uma string
password = ''.join(password_list)
# Sempre limpo o campo antes de gerar uma nova senha
password_entry.delete(0, END)
password_entry.insert(0, password)
# ------ SAVE PASS ----- #
def save():
website = website_entry.get()
email = email_entry.get()
password = password_entry.get()
new_data = {
website: {
"email": email,
"password": password
}
}
if website == "" or email == "" or password == "":
messagebox.showerror("Error", "Please fill out all fields")
return
else:
try:
with open('data.json', 'r') as data_file:
data = json.load(data_file)
except FileNotFoundError:
with open('data.json', 'w') as data_file:
json.dump(new_data, data_file, indent=4)
else:
data.update(new_data)
with open('data.json', 'w') as data_file:
json.dump(data, data_file, indent=4)
finally:
website_entry.delete(0, END)
password_entry.delete(0, END)
# ------ FIND PASSWORD ------- #
def find_password():
website = website_entry.get()
try:
with open('data.json', 'r') as data_file:
data = json.load(data_file)
except FileNotFoundError:
messagebox.showerror("Error", "Arquivo de dados não encontrado")
else:
if website in data:
email = data[website]["email"]
password = data[website]["password"]
messagebox.showinfo(
title=website, message=f"Email: {email}\nPassword: {password}")
else:
messagebox.showinfo(
"Error", f"Nehuma senha cadastrada no site {website}")
# ------ UI SETUP ------- #
window = Tk()
window.title("Gerenciador de Senhas")
window.config(padx=50, pady=50)
canvas = Canvas(height=200, width=200)
logo_image = PhotoImage(file="logo.png")
canvas.create_image(100, 100, image=logo_image)
canvas.grid(row=0, column=1)
# Labels
website_label = Label(text="Website:")
website_label.grid(row=1, column=0)
email_label = Label(text="Email/Username:")
email_label.grid(row=2, column=0)
password_label = Label(text="Password:")
password_label.grid(row=3, column=0)
# Entrys
website_entry = Entry(width=23)
website_entry.grid(row=1, column=1)
website_entry.focus()
email_entry = Entry(width=35)
email_entry.grid(row=2, column=1, columnspan=2)
# insere um email no inicio, se fosse a constante END seria no fim dos caracteres
email_entry.insert(0, "example@email.com")
password_entry = Entry(width=23)
password_entry.grid(row=3, column=1)
# Buttons
search_button = Button(text="Pesquisar", width=10, command=find_password)
search_button.grid(row=1, column=2)
generate_password_button = Button(
text="Gerar Senha", command=generate_password)
generate_password_button.grid(row=3, column=2)
add_button = Button(text="Add", width=36, command=save)
add_button.grid(row=4, column=1, columnspan=2)
window.mainloop()
Projeto Gerador de senhas, para exemplo de algumas funções do tkinter.
streamlit
Streamlit é uma biblioteca de código aberto para desenvolver aplicações web interativas de forma simples e rápida, especialmente voltada para data science, machine learning e análise de dados.
A principal característica do Streamlit é sua facilidade de uso. Em poucas linhas de código, você pode transformar um script Python comum em uma aplicação web interativa e visual, sem a necessidade de entender HTML, CSS ou JavaScript.
O Streamlit funciona como uma aplicação baseada em reatividade, onde a interface do usuário (UI) é recalculada automaticamente sempre que qualquer interação ocorre. Ou seja, cada vez que o usuário interage (clicando no botão, inserindo texto, etc.), o script Python é executado novamente do início ao fim. caso queira guardar alguma informação como variavel para não ser recarregada use a st.session_state que é um dicionário persistente que guarda valores entre interações no Streamlit.
Instalação e Execução streamlit
$ pip install streamlit # instala a biblioteca
$ streamlit run form.py # Executa o arquivo no servidor http://localhost:8501/
| Exemplo aplicação de Filmes
Resultado abaixo

import streamlit as st
import conexao_db
st.title("Filmes")
nome = st.text_input("Nome do filme")
ano = st.number_input("Ano de lançamento", min_value=2010,
max_value=2025)
nota = st.slider("Nota do filme", min_value=1.0, max_value=10.0)
if st.button("Adicionar"):
conexao_db.inserir_filme(nome, ano, nota)
st.success("Filme adicionado com sucesso")
filmes = conexao_db.listar_filmes()
st.header("Lista de Filmes")
st.table(filmes)
import sqlite3
def connection():
connection = sqlite3.connect('filmes.db')
cursor = connection.cursor()
cursor.execute(
"""
CREATE TABLE IF NOT EXISTS filmes(
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome VARCHAR(255) NOT NULL,
ano INTEGER NOT NULL,
nota REAL NOT NULL
);
"""
)
return connection
def inserir_filme(nome, ano, nota):
conn = connection()
cursor = conn.cursor()
cursor.execute('INSERT INTO filmes (nome, ano, nota) VALUES (?, ?, ?)',(nome,ano,nota))
conn.commit()
conn.close()
def listar_filmes():
conn = connection()
cursor = conn.cursor()
cursor.execute('SELECT * FROM filmes')
filmes = cursor.fetchall()
conn.close()
return filmes
import streamlit as st
# Inicializa o contador
if "contador" not in st.session_state:
st.session_state.contador = 0
# Botão para incrementar
if st.button("Clique para contar"):
st.session_state.contador += 1
# Mostra o valor atual
st.write(f"Contador: {st.session_state.contador}")
-
O contador não é resetado ao clicar no botão.
-
Ele se mantém enquanto a sessão estiver ativa no navegador.
Assuntos Relacionados
Gradio
Gradio é uma biblioteca em Python que permite criar interfaces gráficas interativas para modelos de machine learning, APIs ou qualquer outro código Python de forma simples e rápida. Ele é muito usado para criar demonstrações de modelos de IA sem precisar desenvolver um front-end complexo. Documentação pode ser encontrada AQUI. Biblioteca externa precisa ser instalada.
import gradio as gr
def somar(n1, n2):
return n1+n2, "Parabéns pela soma"
iface = gr.Interface(
fn=somar,
inputs=["number","number"], # number é um tipo de entrada numerica
outputs=["number","text"], # como a função tem dois retornos coloco na ordem
title="Calculadora",
description="Soma de dois números",
)
iface.launch()
matplotlib
A matplotlib é uma das bibliotecas externas (necessário instalar com pip) mais populares do Python para visualização de dados — especialmente gráficos 2D.
É uma biblioteca poderosa e flexível para criar gráficos e visualizações. Ela te permite gerar diversos tipos de graficos.
📈 Tipos comuns de gráficos:
| Tipo | Função |
|---|---|
| Linha | plt.plot() |
| Barras | plt.bar() ou plt.barh() |
| Pizza | plt.pie() |
| Dispersão | plt.scatter() |
| Histograma | plt.hist() |
| Boxplot | plt.boxplot() |
import matplotlib.pyplot as plt
# Dados
x = [1, 2, 3, 4, 5]
y = [10, 20, 25, 30, 40]
# Criar gráfico
plt.plot(x, y)
# Títulos e rótulos
plt.title('Crescimento de vendas')
plt.xlabel('Mês')
plt.ylabel('Vendas')
# Mostrar
plt.show()
Ela tem uma interface chamada pyplot (importada como plt), que é inspirada no estilo do MATLAB — bem direta e procedural.
plt.plot(x, y, color='green', linestyle='--', marker='o', label='vendas')
plt.legend()
plt.savefig("grafico.png") # Salvar como imagem
Flet
O Flet é um framework (baseado no flutter) para criar interfaces gráficas de usuário (GUI) modernas e responsivas usando apenas Python, sem precisar mexer diretamente com HTML, CSS ou JavaScript. O Flet tem o hot reload (recarrega automaticamente quaisquer alterações salvas).
Tabela com as principais propriedades do page no Flet:
| Propriedade | Tipo / Enum | O que faz |
|---|---|---|
title |
str |
Define o título da janela/navegador. |
bgcolor |
str ou ft.colors |
Define a cor de fundo da página. |
horizontal_alignment |
ft.CrossAxisAlignment |
Alinha os elementos horizontalmente (esquerda, centro, direita, etc). |
vertical_alignment |
ft.MainAxisAlignment |
Alinha os elementos verticalmente (topo, centro, base, etc). |
theme_mode |
ft.ThemeMode.LIGHT / DARK / SYSTEM |
Define o tema claro/escuro da interface. |
window_width |
float |
Define a largura da janela (em apps desktop). |
window_height |
float |
Define a altura da janela. |
window_resizable |
bool |
Permite ou não redimensionar a janela. |
window_maximizable |
bool |
Permite ou não maximizar. |
window_minimizable |
bool |
Permite ou não minimizar. |
window_full_screen |
bool |
Abre a janela em tela cheia. |
padding |
int / ft.Padding |
Define o espaçamento interno da página. |
scroll |
ft.ScrollMode.AUTO / ALWAYS / NONE |
Define se a rolagem está habilitada. |
fonts |
dict[str, str] |
Define fontes personalizadas. |
theme |
ft.Theme |
Define o tema customizado da interface. |
add(...) |
Método | Adiciona elementos à página. |
update() |
Método | Atualiza a página após mudanças dinâmicas. |
clean() |
Método | Remove todos os elementos da página. |
Comandos Flet
Se usar apenas o run, ele procura o arquivo main.py para executar.
Obs.: pode rodar o programa com python arquivo.py também.
$ pip install flet # instala a biblioteca
$ flet run arquivo.py # roda em modo desktop
$ flet run arquivo.py --web # roda em modo web
import flet as ft
# usando tipy hint aqui
def main(page:ft.Page):
page.title = "Flet" # Título da página
# tambem tem cores definidas do proprio flet, ft.colors.BLUE...
page.bgcolor = "gray"
# alinhar horizontalmente os elementos dentro da page — ou seja, no eixo principal horizontal# Adiciona padding a página, ou seja, espaço entre os elementos e as bordas da página. (da esquerda para a direita).
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.vertical_alignment = ft.MainAxisAlignment.CENTER # Alinhamento vertical
# Adiciona padding a página, ou seja, espaço entre os elementos e as bordas da página.
page.padding = ft.padding.all(100)
texto_teste = ft.Text(
value="Texto de teste",
theme_style=ft.TextThemeStyle.DISPLAY_LARGE,
bgcolor=ft.colors.WHITE30,
max_lines=2, # Limita o número de linhas do texto a 2
# Adiciona reticências se o texto for muito longo e não couber no limite de linhas definido acima
overflow=ft.TextOverflow.ELLIPSIS,
style=ft.TextStyle(
color=ft.colors.RED_900,
font_family="Arial",
),
text_align=ft.TextAlign.CENTER, # Alinhamento do texto dentro do elemento
)
estilo_span1 = ft.TextStyle(
color=ft.Colors.BLUE_900,
decoration=ft.TextDecoration.UNDERLINE,
)
texto2_span = ft.Text(
spans=[
ft.TextSpan(text="Texto SPAN 1",
url='https://www.google.com',
style=estilo_span1),
ft.TextSpan(text="Texto SPAN 2",
style=ft.TextStyle(
color=ft.Colors.RED_900,
font_family="Arial",
)),
],
)
# Adiciona objetos de texto e etc à página, (ao adicionar a interface atualiza automaticamente)
page.add(
ft.Text(value="Hello World"),
ft.Container(ft.Text("Hello World 2"), bgcolor=ft.Colors.BLUE_50), # Container com cor de fundo
texto_teste,
texto2_span
)
# Atualiza a página para refletir as mudanças, usado para atualizar dinamicamente apos a interface criada
# page.update()
# Inicia a aplicação e usa a função main como o ponto inicial para montar a interface.
ft.app(target=main)
import flet as ft
def main(page: ft.Page):
page.theme_mode = ft.ThemeMode.SYSTEM
page.padding = 50
# IMAGEM UNICA
img = ft.Image(
src="https://www.w3schools.com/w3images/lights.jpg",
border_radius=ft.border_radius.all(40),
tooltip="Minha imagem"
)
# CARROSEL DE IMAGENS EM LINHA
# Cria uma linha horizontal de elementos
images_em_linha = ft.Row(expand=1,wrap=False, scroll="always")
for i in range(0, 30):
# Esse trecho adiciona elementos dinamicamente à linha (Row).
images_em_linha.controls.append(
ft.Image(
src=f"https://picsum.photos/200/200?{i}",
width=200,
height=200,
# como a imagem se encaixa dentro do tamanho, NONE = tamanho original (não redimensiona), podendo vazar fora da moldura.
fit=ft.ImageFit.NONE,
# Isso define se a imagem vai se repetir para preencher o espaço.
repeat=ft.ImageRepeat.NO_REPEAT,
border_radius=ft.border_radius.all(40)
)
)
# Adicionando Icones
icons_row = ft.Row(
controls=[
ft.Icon(name=ft.Icons.FAVORITE, color=ft.Colors.PINK, size=30),
ft.Icon(name=ft.Icons.AUDIO_FILE, color=ft.Colors.GREEN, size=30),
ft.Icon(name=ft.Icons.BEACH_ACCESS, color=ft.Colors.BLUE, size=30),
ft.Icon(name="settings", color='#c1c1c1', size=30),
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=20
)
page.add(
# img,
images_em_linha,
ft.Column(
controls=[icons_row],
)
)
ft.app(target=main)
| Parâmetro | Valor | O que faz |
|---|---|---|
expand=1 |
1 |
Faz o Row expandir para ocupar o espaço disponível dentro do pai |
wrap=False |
False |
Impede que os elementos "quebrem linha" — ou seja, eles continuam na mesma linha mesmo se ultrapassarem o tamanho da tela |
scroll="always" |
"always" |
Ativa a barra de rolagem horizontal, sempre visível (ideal pro carrossel!) |
import flet as ft
def main(page:ft.Page):
botao_elevado = ft.ElevatedButton(text="Botão Simples")
botao_desativado = ft.ElevatedButton(text="Botão Desativado", disabled=True)
botao_icone = ft.ElevatedButton(text="Botão com icone", icon="access_time")
botao_icone_colorido = ft.ElevatedButton(text="Botão com icone colorido", icon="park_rounded", icon_color="green400")
botao_conteudo_customizado = ft.ElevatedButton(
width=150,
content=ft.Row([
ft.Icon(name=ft.Icons.FAVORITE, color="pink"),
ft.Icon(name=ft.Icons.BEACH_ACCESS, color="blue"),
ft.Icon(name=ft.Icons.AUDIO_FILE, color="green"),
])
)
botao_texto_composto = ft.ElevatedButton(
content=ft.Container(
content= ft.Column(
[
ft.Text("Botão Composto", size=20),
ft.Text("Segundo Texto")
],
alignment=ft.MainAxisAlignment.CENTER,
spacing=5
),
padding=ft.padding.all(10)
)
)
def button_clicked(e):
botao_evento.data += 1
texto_evento.value = f"O botão acima foi clicado {botao_evento.data} vezes"
page.update()
botao_evento = ft.ElevatedButton(text="Botão com evento", on_click=button_clicked, data=0)
texto_evento = ft.Text()
page.add(
botao_elevado,
botao_desativado,
botao_icone,
botao_icone_colorido,
botao_evento,
texto_evento,
botao_conteudo_customizado,
botao_texto_composto
)
ft.app(target=main)
import flet as ft
from time import sleep
def main(page:ft.Page):
barra_progresso = ft.ProgressBar(width=400)
texto_barra_progresso = ft.Text("Progresso Linear", theme_style="headlineSmall")
barra_indeterminada = ft.ProgressBar(width=400, color="amber", bgcolor="#eeeeee")
texto_barra_indeterminada = ft.Text("Progresso Indeterminado", theme_style="headlineSmall")
barra_fixa = ft.ProgressBar(width=400, color="purple", bgcolor="#eeeeee", value=0.3)
texto_barra_fixa = ft.Text("Barra Fixa em 30%", theme_style="headlineSmall")
barra_cupertino = ft.CupertinoActivityIndicator(
radius=50,
color=ft.Colors.RED,
animating=True
)
page.add(
# Coloco os textos e as barras em uma unica coluna (ficar um abaixo do outro), mas sem column também apareceria na ordem que colocar
ft.Column([
texto_barra_progresso,
ft.Text("Aguarde..."),
barra_progresso,
texto_barra_indeterminada,
barra_indeterminada,
texto_barra_fixa,
barra_fixa,
barra_cupertino,
]),
)
for i in range(0,101):
barra_progresso.value = i*0.01
sleep(0.1)
page.update()
ft.app(target=main)
import flet as ft
def main(page: ft.Page):
page.title = "Exemplos de Inputs"
page.scroll = "auto"
page.padding = 20
# Campo de texto simples
nome_input = ft.TextField(
label="Nome",
hint_text="Digite seu nome",
width=300
)
# Campo de texto com senha
senha_input = ft.TextField(
label="Senha",
hint_text="Digite sua senha",
password=True,
can_reveal_password=True,
width=300
)
# Campo numérico
idade_input = ft.TextField(
label="Idade",
hint_text="Digite sua idade",
keyboard_type=ft.KeyboardType.NUMBER,
width=150
)
# Caixa de seleção (dropdown)
genero_select = ft.Dropdown(
label="Gênero",
width=300,
options=[
ft.dropdown.Option("Masculino"),
ft.dropdown.Option("Feminino"),
ft.dropdown.Option("Outro"),
]
)
# Caixa de verificação (checkbox)
checkbox_novidades = ft.Checkbox(
label="Desejo receber novidades por e-mail",
value=False,
on_change=lambda e: print(f"Checkbox marcado?: {e.control.value}")
)
# Switch (toggle)
modo_escuro_switch = ft.Switch(label="Modo escuro")
# Botão
botao_enviar = ft.ElevatedButton(text="Enviar", on_click=lambda e: print("Formulário enviado"))
# Agrupando tudo numa coluna com espaçamento
page.add(
ft.Column(
controls=[
ft.Text("Formulário de Cadastro", theme_style=ft.TextThemeStyle.HEADLINE_MEDIUM),
nome_input,
senha_input,
idade_input,
genero_select,
checkbox_novidades,
modo_escuro_switch,
botao_enviar
],
spacing=15,
alignment=ft.MainAxisAlignment.START,
)
)
ft.app(target=main)
import flet as ft
# Função principal que será executada ao iniciar o app
def main(page: ft.Page):
# Alinha horizontalmente os elementos no centro da página (eixo cruzado = vertical, pois Flet usa eixo principal como vertical em Column)
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
# Estilo reutilizável para os botões do banner
action_button_style = ft.ButtonStyle(color=ft.colors.BLUE)
# Função chamada ao clicar em um dos botões do banner
def close_banner(e):
# Fecha o banner
page.close(banner)
# Adiciona um texto à página indicando qual botão foi clicado (usa o texto do botão: e.control.text)
page.add(ft.Text("Clicado: " + e.control.text))
# Criação do banner que aparecerá na parte superior da página
banner = ft.Banner(
bgcolor=ft.colors.AMBER_100, # Cor de fundo do banner
leading=ft.Icon( # Ícone à esquerda do banner
ft.icons.WARNING_AMBER_ROUNDED,
color=ft.Colors.AMBER,
size=40
),
content=ft.Text( # Texto principal do banner
value="OOps, there were some errors while trying to delete the file.",
color=ft.colors.BLACK
),
actions=[ # Botões de ação dentro do banner
ft.TextButton(text="Retry", style=action_button_style, on_click=close_banner),
ft.TextButton(text="Ignore", style=action_button_style, on_click=close_banner),
ft.TextButton(text="Cancel", style=action_button_style, on_click=close_banner)
]
)
# Função para mostrar um diálogo não-modal (o usuário pode interagir com a página enquanto ele está aberto)
def show_non_modal_dialog(e):
# Cria um AlertDialog não-modal
dlg = ft.AlertDialog(
title=ft.Text("Hi, this is a non-modal dialog!"),
on_dismiss=lambda e: page.add(ft.Text("non-modal dialog dismissed")) # Quando o usuário fecha, adiciona texto à página
)
# Abre o diálogo
page.open(dlg)
# Função para mostrar um diálogo modal (o usuário NÃO pode interagir com o restante da página até fechá-lo)
def show_modal_dialog(e):
# Função chamada quando um botão dentro do diálogo for clicado
def handle_close(e):
page.close(dialog_modal) # Fecha o diálogo
page.add(ft.Text(f"Modal dialog closed with action: {e.control.text}")) # Mostra qual botão foi clicado
# Cria o diálogo modal
dialog_modal = ft.AlertDialog(
modal=True, # Torna o diálogo modal (bloqueia interações fora dele)
title=ft.Text("Please Confirm?"), # Título do diálogo
content=ft.Text("Do you Really want to delete all those files?"), # Texto de corpo
actions=[ # Botões de ação
ft.TextButton("Yes", on_click=handle_close),
ft.TextButton("No", on_click=handle_close)
],
actions_alignment=ft.MainAxisAlignment.END, # Alinha os botões à direita
on_dismiss=lambda e: page.add(ft.Text("Modal dialog dismissed")) # Mensagem caso o diálogo seja fechado de outra forma
)
# Abre o diálogo modal
page.open(dialog_modal)
# Adiciona os botões principais na página
page.add(
# Botão para abrir o diálogo não-modal
ft.ElevatedButton("Open non-modal dialog", on_click=show_non_modal_dialog),
# Botão para abrir o diálogo modal
ft.ElevatedButton("Open modal dialog", on_click=show_modal_dialog),
# Botão para mostrar o banner
ft.ElevatedButton("Show Banner", on_click=lambda e: page.open(banner))
)
# Inicializa o aplicativo chamando a função main
ft.app(target=main)
# Importa o módulo Flet, que é usado para criar interfaces gráficas em Python.
import flet as ft
# Função principal que recebe a página como argumento.
def main(page: ft.Page):
# ----------- ABAS COM ÍCONES (NavigationBar) ----------- #
# Define o título da janela do app
page.title = "NavigationBar"
# Cria uma barra de navegação na parte inferior da tela com 3 abas
page.navigation_bar = ft.NavigationBar(
destinations=[
# Primeira aba: ícone de exploração
ft.NavigationBarDestination(icon=ft.icons.EXPLORE, label="Explore"),
# Segunda aba: ícone de transporte
ft.NavigationBarDestination(icon=ft.icons.COMMUTE, label="Commute"),
# Terceira aba: muda o ícone quando está selecionado
ft.NavigationBarDestination(
icon=ft.icons.BOOKMARK_BORDER, # ícone padrão
label="Explore",
selected_icon=ft.icons.BOOKMARK # ícone quando selecionado
),
]
)
# Adiciona um texto simples no corpo da página
page.add(ft.Text("Body"))
# ----------- BARRA HAMBÚRGUER (NavigationDrawer) ----------- #
# Centraliza horizontalmente os elementos adicionados à página
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
# Função que será chamada quando o drawer for fechado (dismissed)
def handle_dismissal(e):
# Adiciona um texto na tela indicando que o drawer foi fechado
page.add(ft.Text("Drawer dismissed"))
# Função chamada quando o usuário muda a seleção no drawer
def handle_change(e):
# Mostra na tela o índice do item selecionado
page.add(ft.Text(f"Selected Index changed: {e.selected_index}"))
# Cria o drawer (menu lateral) com itens de navegação
drawer = ft.NavigationDrawer(
on_dismiss=handle_dismissal, # chama a função ao fechar o drawer
on_change=handle_change, # chama a função ao selecionar item
controls = [ # lista de itens exibidos no drawer
ft.Container(height=12), # espaçamento superior
# Primeiro item do drawer
ft.NavigationDrawerDestination(
label="Item 1",
icon_content=ft.Icon(ft.icons.DOOR_BACK_DOOR_OUTLINED), # ícone padrão
selected_icon=ft.Icons.DOOR_BACK_DOOR # ícone quando selecionado
),
# Linha divisória
ft.Divider(thickness=2),
# Segundo item do drawer
ft.NavigationDrawerDestination(
label="Item 2",
icon_content=ft.Icon(ft.icons.MAIL_OUTLINED),
selected_icon=ft.Icons.MAIL
),
# Terceiro item do drawer
ft.NavigationDrawerDestination(
label="Item 3",
icon_content=ft.Icon(ft.icons.PHONE_OUTLINED),
selected_icon=ft.Icons.PHONE
),
]
)
# Adiciona um botão na tela que abre o drawer ao ser clicado
page.add(ft.ElevatedButton("Show drawer", on_click=lambda e: page.open(drawer)))
# Inicia o aplicativo executando a função main
ft.app(target=main)
import flet as ft
def main(page: ft.Page):
# Título da página
page.title = "Exemplo de ExpansionPanelList"
# Função chamada ao abrir ou fechar o painel
def on_change(e):
page.add(ft.Text(f"Painel {e.control.selected_index + 1} foi clicado"))
# Cria a lista de painéis expansíveis
expansion_panel_list = ft.ExpansionPanelList(
# Define o comportamento quando um painel é clicado
expand_icon_color=ft.colors.BLUE,
divider_color=ft.colors.GREY,
elevation=3,
controls=[
# Primeiro painel
ft.ExpansionPanel(
header=ft.Text("Painel 1"),
content=ft.Text("Conteúdo do painel 1"),
expanded=False,
),
# Segundo painel
ft.ExpansionPanel(
header=ft.Text("Painel 2"),
content=ft.Text("Conteúdo do painel 2"),
expanded=False,
),
# Terceiro painel
ft.ExpansionPanel(
header=ft.Text("Painel 3"),
content=ft.Text("Conteúdo do painel 3"),
expanded=False,
),
],
on_change=on_change # Chama a função quando um painel muda de estado
)
# Adiciona à página
page.add(expansion_panel_list)
ft.app(target=main)
# Importa o módulo Flet, usado para criar interfaces gráficas com Python
import flet as ft
# Define a função principal que recebe a página como argumento
def main(page: ft.Page):
# Cria o conteúdo do card, usando uma coluna (empilha os elementos verticalmente)
card_content = ft.Column(
[
# Cria um ListTile (componente com ícone, título e subtítulo) para o cabeçalho do card
ft.ListTile(
leading=ft.Icon(ft.Icons.CAKE), # Ícone de bolo (símbolo de aniversário)
title=ft.Text("Feliz aniversário!", size=25, weight="bold"), # Título em negrito e fonte maior
subtitle=ft.Text("Que seu dia seja repleto de alegrias, risadas e muito amor.") # Texto abaixo do título
),
# Cria uma linha para conter os botões "Compartilhar" e "Enviar votos"
ft.Row(
[
# Primeiro botão: "Compartilhar"
ft.TextButton(
"Compartilhar",
# Quando clicado, exibe uma mensagem na tela com cor verde
on_click=lambda _: page.add(
ft.Text("Mensagem compartilhada com sucesso", color=ft.colors.GREEN_600)
),
),
# Segundo botão: "Enviar votos" (sem ação definida)
ft.TextButton("Enviar votos")
]
)
],
# Alinha os itens da coluna ao final (parte inferior do card)
alignment=ft.MainAxisAlignment.END
)
# Adiciona um Card à página com o conteúdo definido acima
page.add(
ft.Card(
content=ft.Container(
content=card_content, # Insere o conteúdo dentro do card
width=400, # Define a largura do card
padding=20 # Espaçamento interno (padding) de 20px em todos os lados
)
)
)
# Executa o aplicativo Flet e chama a função 'main' como ponto de entrada
ft.app(target=main)
import flet as ft
def main(page: ft.Page):
page.title = "Exemplo de GridView com Imagens"
page.scroll = "auto" # Permite rolagem automática se os itens ultrapassarem a altura da tela
# Lista de URLs de imagens
imagens = [
"https://picsum.photos/200/200?1",
"https://picsum.photos/200/200?2",
"https://picsum.photos/200/200?3",
"https://picsum.photos/200/200?4",
"https://picsum.photos/200/200?5",
"https://picsum.photos/200/200?6"
]
# Cria os containers com imagens (dentro de uma lista por compreensão)
itens_grid = [
ft.Container(
content=ft.Image(src=url, fit=ft.ImageFit.COVER),
width=150,
height=150,
border_radius=10,
bgcolor=ft.colors.GREY_200,
padding=5
)
for url in imagens
]
# Cria um GridView para exibir os itens
grid = ft.GridView(
expand=True, # Ocupa o espaço disponível
runs_count=3, # Número de colunas (itens por linha)
max_extent=200, # Largura máxima por item (controla a quebra de linha automaticamente)
child_aspect_ratio=1.0, # Mantém o aspecto quadrado
spacing=10, # Espaço horizontal entre itens
run_spacing=10, # Espaço vertical entre linhas
controls=itens_grid # Adiciona os itens ao grid
)
# Adiciona o grid à página
page.add(grid)
# Executa o app
ft.app(target=main)