Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import ttk, messagebox
- import matplotlib
- # Configura o backend do Matplotlib para funcionar com Tkinter
- matplotlib.use('TkAgg')
- from matplotlib.figure import Figure
- from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
- import numpy as np
- class AppPessoas(tk.Tk):
- """Classe principal da aplicação Tkinter."""
- def __init__(self):
- super().__init__()
- self.title("Cadastro e Gráfico de Pessoas")
- self.geometry("800x600")
- # Lista para armazenar os dados de pessoas: [{"idade": 30, "peso": 75}, ...]
- self.dados_pessoas = []
- # Configura as abas
- self.notebook = ttk.Notebook(self)
- self.notebook.pack(pady=10, padx=10, expand=True, fill="both")
- # Cria as abas
- self.aba_cadastro = ttk.Frame(self.notebook)
- self.aba_grafico = ttk.Frame(self.notebook)
- self.notebook.add(self.aba_cadastro, text="1. Cadastro")
- self.notebook.add(self.aba_grafico, text="2. Gráfico")
- # Vincula a função de atualização ao evento de mudança de aba
- self.notebook.bind("<<NotebookTabChanged>>", self.on_tab_change)
- # Configura o conteúdo de cada aba
- self.setup_aba_cadastro()
- self.setup_aba_grafico()
- def setup_aba_cadastro(self):
- """Configura os widgets na aba de Cadastro."""
- # Frame principal para centralizar
- frame_cadastro = ttk.Frame(self.aba_cadastro, padding="20")
- frame_cadastro.pack(expand=True, anchor="center")
- # Rótulo e campo para Idade
- ttk.Label(frame_cadastro, text="Idade (anos):").grid(row=0, column=0, pady=10, sticky="w")
- self.entry_idade = ttk.Entry(frame_cadastro, width=15)
- self.entry_idade.grid(row=0, column=1, pady=10, padx=5, sticky="ew")
- # Rótulo e campo para Peso
- ttk.Label(frame_cadastro, text="Peso (kg):").grid(row=1, column=0, pady=10, sticky="w")
- self.entry_peso = ttk.Entry(frame_cadastro, width=15)
- self.entry_peso.grid(row=1, column=1, pady=10, padx=5, sticky="ew")
- # Botão para adicionar
- botao_adicionar = ttk.Button(frame_cadastro, text="Adicionar Pessoa", command=self.adicionar_pessoa)
- botao_adicionar.grid(row=2, column=0, columnspan=2, pady=20)
- # Rótulo para mostrar a contagem de pessoas
- self.label_contagem = ttk.Label(frame_cadastro, text=f"Pessoas cadastradas: {len(self.dados_pessoas)}")
- self.label_contagem.grid(row=3, column=0, columnspan=2, pady=10)
- def adicionar_pessoa(self):
- """Coleta, valida e armazena os dados de idade e peso."""
- try:
- idade = int(self.entry_idade.get())
- peso = float(self.entry_peso.get().replace(',', '.'))
- if idade <= 0 or peso <= 0:
- raise ValueError("Idade e Peso devem ser maiores que zero.")
- # Armazena os dados
- self.dados_pessoas.append({"idade": idade, "peso": peso})
- # Limpa os campos de entrada
- self.entry_idade.delete(0, tk.END)
- self.entry_peso.delete(0, tk.END)
- # Atualiza a contagem
- self.label_contagem.config(text=f"Pessoas cadastradas: {len(self.dados_pessoas)}")
- messagebox.showinfo("Sucesso", f"Pessoa adicionada: Idade {idade}, Peso {peso}kg.")
- except ValueError as e:
- messagebox.showerror("Erro de Entrada", f"Por favor, insira valores válidos: {e}")
- except Exception as e:
- messagebox.showerror("Erro", f"Ocorreu um erro: {e}")
- def setup_aba_grafico(self):
- """Configura a área de desenho do gráfico na aba de Gráfico."""
- # Cria a Figura (área de desenho) do Matplotlib
- self.figura = Figure(figsize=(5, 5), dpi=100)
- self.eixo = self.figura.add_subplot(111)
- # Cria o Canvas do Tkinter a partir da Figura
- self.canvas = FigureCanvasTkAgg(self.figura, master=self.aba_grafico)
- # Adiciona o widget do canvas à aba
- self.canvas_widget = self.canvas.get_tk_widget()
- self.canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
- # Desenha o gráfico inicial vazio
- self.plotar_grafico()
- def plotar_grafico(self):
- """Gera o gráfico de Dispersão (Scatter Plot) com frequência de peso por idade."""
- # Limpa o gráfico anterior
- self.eixo.clear()
- if not self.dados_pessoas:
- self.eixo.text(0.5, 0.5, 'Nenhum dado cadastrado para exibir.',
- ha='center', va='center', transform=self.eixo.transAxes)
- self.figura.canvas.draw()
- return
- # 1. Preparar os dados para contagem de frequência
- # Cria tuplas (idade, peso) e conta a frequência de cada combinação
- combinacoes = [(d['idade'], d['peso']) for d in self.dados_pessoas]
- from collections import Counter
- frequencias = Counter(combinacoes)
- # 2. Separar os dados contados
- idades = [c[0] for c in frequencias.keys()]
- pesos = [c[1] for c in frequencias.keys()]
- contagens = np.array(list(frequencias.values()))
- # 3. Mapear a contagem para o tamanho do ponto (escala visual)
- # O tamanho (s) dos pontos no scatter plot será proporcional à frequência
- # Usamos log para suavizar grandes diferenças e adicionamos um offset
- tamanhos = (np.log(contagens + 1) * 200) + 50
- # 4. Desenhar o gráfico de dispersão (Scatter Plot)
- scatter = self.eixo.scatter(idades, pesos, s=tamanhos, alpha=0.6, edgecolors='w', linewidth=1)
- # 5. Configurar rótulos e título
- self.eixo.set_title("Frequência de Peso por Idade (Tamanho do Ponto = Frequência)")
- self.eixo.set_xlabel("Idade (anos)")
- self.eixo.set_ylabel("Peso (kg)")
- self.eixo.grid(True, linestyle='--', alpha=0.7)
- self.eixo.margins(0.1)
- # Garante que os valores dos eixos sejam inteiros se forem todos inteiros
- if all(isinstance(i, int) for i in idades) and idades:
- self.eixo.xaxis.set_major_locator(matplotlib.ticker.MaxNLocator(integer=True))
- # 6. Forçar o redesenho do canvas
- self.figura.canvas.draw()
- def on_tab_change(self, event):
- """Chamado quando o usuário muda de aba. Atualiza o gráfico se for para a aba de Gráfico."""
- aba_selecionada = self.notebook.tab(self.notebook.select(), "text")
- if aba_selecionada == "2. Gráfico":
- self.plotar_grafico()
- # Ponto de entrada do programa
- if __name__ == "__main__":
- app = AppPessoas()
- app.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment