From 417c534d6e23409565a57331d8bc689be39ec3b5 Mon Sep 17 00:00:00 2001 From: Emersonjsc Date: Wed, 2 Jul 2025 10:05:06 -0300 Subject: [PATCH] Layput front --- main.py | 2 +- persistencia/banco_dados.py | 8 ++ visao/cli.py | 2 +- visao/componentes/dialogo_adicionar_pet.py | 54 +++++++++ visao/frames/frame_adocao.py | 20 ++++ visao/frames/frame_pessoa.py | 105 ++++++++++++++++- visao/frames/frame_pet.py | 125 +++++++++++++++++++++ visao/tela_principal.py | 25 ++++- 8 files changed, 332 insertions(+), 9 deletions(-) create mode 100644 visao/componentes/dialogo_adicionar_pet.py create mode 100644 visao/frames/frame_adocao.py create mode 100644 visao/frames/frame_pet.py diff --git a/main.py b/main.py index f306586..72f4d79 100644 --- a/main.py +++ b/main.py @@ -2,5 +2,5 @@ from visao.cli import InterfaceTexto from visao.tela_principal import TelaPrincipal if __name__ == "__main__": - app = TelaPrincipal() + app = InterfaceTexto() app.mainloop() diff --git a/persistencia/banco_dados.py b/persistencia/banco_dados.py index 1f78fc0..81e5d30 100644 --- a/persistencia/banco_dados.py +++ b/persistencia/banco_dados.py @@ -8,3 +8,11 @@ class BancoDeDados: self.pessoas = Persistente() self.pets = Persistente() self.adocoes = Persistente() + + def obter_proximo_id(self): + ids_pessoas = [p.id for p in self.pessoas.listar_todos()] + ids_pets = [p.id for p in self.pets.listar_todos()] + ids_adocoes = [a.id for a in self.adocoes.listar_todos()] + + todos_ids = ids_pessoas + ids_pets + ids_adocoes + return max(todos_ids) + 1 if todos_ids else 1 diff --git a/visao/cli.py b/visao/cli.py index 1413274..ccf5866 100644 --- a/visao/cli.py +++ b/visao/cli.py @@ -10,7 +10,7 @@ class InterfaceTexto: self.bd = BancoDeDados() self.proximo_id = 1 - def executar(self): + def mainloop(self): while True: print("\n=== Menu Principal ===") print("1. Pessoas") diff --git a/visao/componentes/dialogo_adicionar_pet.py b/visao/componentes/dialogo_adicionar_pet.py new file mode 100644 index 0000000..34661d8 --- /dev/null +++ b/visao/componentes/dialogo_adicionar_pet.py @@ -0,0 +1,54 @@ +import tkinter as tk +from tkinter import messagebox + +class DialogoAdicionarPet(tk.Toplevel): + def __init__(self, parent): + super().__init__(parent) + self.transient(parent) + self.title("Adicionar Novo Pet") + self.parent = parent + self.result = None + + body = tk.Frame(self, padx=15, pady=15) + self.initial_focus = self.criar_formulario(body) + body.pack() + + self.criar_botoes() + + self.grab_set() # Torna a janela modal + self.protocol("WM_DELETE_WINDOW", self._on_cancel) + self.geometry(f"+{parent.winfo_rootx()+50}+{parent.winfo_rooty()+50}") + self.initial_focus.focus_set() + self.wait_window(self) # Pausa a execução até que a janela seja fechada + + def criar_formulario(self, master): + tk.Label(master, text="Nome:").grid(row=0, column=0, sticky="w", pady=3) + self.nome_entry = tk.Entry(master, width=30) + self.nome_entry.grid(row=0, column=1, padx=5, pady=3) + + tk.Label(master, text="Espécie:").grid(row=1, column=0, sticky="w", pady=3) + self.especie_entry = tk.Entry(master, width=30) + self.especie_entry.grid(row=1, column=1, padx=5, pady=3) + + return self.nome_entry # Define o foco inicial + + def criar_botoes(self): + box = tk.Frame(self, pady=5) + tk.Button(box, text="Adicionar", width=10, command=self._on_ok, default=tk.ACTIVE).pack(side=tk.LEFT, padx=5) + tk.Button(box, text="Cancelar", width=10, command=self._on_cancel).pack(side=tk.LEFT, padx=5) + self.bind("", self._on_ok) + self.bind("", self._on_cancel) + box.pack() + + def _on_ok(self, event=None): + nome = self.nome_entry.get().strip() + especie = self.especie_entry.get().strip() + if not nome or not especie: + messagebox.showwarning("Campos Vazios", "Por favor, preencha o nome e a espécie.", parent=self) + return + self.result = {"nome": nome, "especie": especie} + self._on_cancel() + + def _on_cancel(self, event=None): + self.parent.focus_set() + self.destroy() \ No newline at end of file diff --git a/visao/frames/frame_adocao.py b/visao/frames/frame_adocao.py new file mode 100644 index 0000000..2115100 --- /dev/null +++ b/visao/frames/frame_adocao.py @@ -0,0 +1,20 @@ +import tkinter as tk +from tkinter import ttk, messagebox + + +class FrameAdocao(tk.Frame): + def __init__(self, master=None, bd=None): + super().__init__(master, bg="#1e1e1e") + self.bd = bd + self._criar_layout() + + def _criar_layout(self): + # Título da seção + titulo_label = tk.Label( + self, + text="GERENCIAR ADOÇÕES", + font=("Arial", 24, "bold"), + bg="#1e1e1e", + fg="white" + ) + titulo_label.pack(pady=20) \ No newline at end of file diff --git a/visao/frames/frame_pessoa.py b/visao/frames/frame_pessoa.py index 43f65d3..692970b 100644 --- a/visao/frames/frame_pessoa.py +++ b/visao/frames/frame_pessoa.py @@ -1,4 +1,7 @@ import tkinter as tk +from tkinter import ttk, messagebox, simpledialog + +from modelo.pessoa import Pessoa class FramePessoas(tk.Frame): def __init__(self, master=None, bd=None): @@ -15,4 +18,104 @@ class FramePessoas(tk.Frame): bg="#1e1e1e", fg="white" ) - titulo_label.pack(pady=20) \ No newline at end of file + titulo_label.pack(pady=20) + + # Estilo para a Treeview + style = ttk.Style() + style.theme_use("default") + style.configure("Treeview", + background="#2c2c2c", # Cor de fundo da Treeview + foreground="white", + rowheight=25, # Altura da linha + fieldbackground="#2c2c2c", + bordercolor="#2c2c2c", + borderwidth=0) + style.map('Treeview', background=[('selected', '#1f6aa5')]) + + style.configure("Treeview.Heading", + background="#2c2c2c", + foreground="white", + font=("Arial", 12, "bold"), + relief="flat") + style.map("Treeview.Heading", + background=[('active', '#3c3c3c')]) + + # Frame para a Treeview e Scrollbar + tree_container = tk.Frame(self, bg="#1e1e1e") + tree_container.pack(pady=10, padx=20, fill="both", expand=True) + + self.tree = ttk.Treeview(tree_container, columns=("id", "nome"), show="headings") + self.tree.heading("id", text="ID") + self.tree.heading("nome", text="Nome", anchor="w") + + + self.tree.column("id", width=100, anchor="center", stretch=tk.NO) + self.tree.column("nome", anchor="w", stretch=tk.YES) + + scrollbar = ttk.Scrollbar(tree_container, orient="vertical", command=self.tree.yview) + self.tree.configure(yscrollcommand=scrollbar.set) + + self.tree.pack(side="left", fill="both", expand=True) + scrollbar.pack(side="right", fill="y") + + self.popular_treeview() + + # Frame para os botões de ação + botoes_frame = tk.Frame(self, bg="#1e1e1e") + botoes_frame.pack(pady=10, padx=20, fill="x") + + # Botão Adicionar + btn_adicionar = tk.Button( + botoes_frame, + text="Adicionar", + command=self.adicionar_pessoa, + bg="#4CAF50", + fg="white", + font=("Arial", 12), + relief="flat", + padx=10, + pady=5 + ) + btn_adicionar.pack(side="left", padx=5) + + # Botão Apagar + btn_apagar = tk.Button( + botoes_frame, + text="Apagar", + command=self.apagar_pessoa, + bg="#f44336", + fg="white", + font=("Arial", 12), + relief="flat", + padx=10, + pady=5 + ) + btn_apagar.pack(side="left", padx=5) + + def popular_treeview(self): + for i in self.tree.get_children(): + self.tree.delete(i) + for pessoa in self.bd.pessoas.listar_todos(): + self.tree.insert("", "end", values=(pessoa.id, pessoa.nome)) + + def adicionar_pessoa(self): + nome = simpledialog.askstring("Adicionar Pessoa", "Digite o nome da nova pessoa:", parent=self) + if nome: + proximo_id = self.bd.obter_proximo_id() + nova_pessoa = Pessoa(proximo_id, nome) + self.bd.pessoas.inserir(nova_pessoa) + self.popular_treeview() + messagebox.showinfo("Sucesso", "Pessoa adicionada com sucesso.") + + def apagar_pessoa(self): + selecionado = self.tree.selection() + if not selecionado: + messagebox.showwarning("Aviso", "Por favor, selecione uma pessoa para apagar.") + return + + item = self.tree.item(selecionado[0]) + id_pessoa, nome_pessoa = item['values'] + if messagebox.askyesno("Confirmar", f"Tem certeza que deseja apagar '{nome_pessoa}'?"): + self.bd.pessoas.remover(id_pessoa) + self.popular_treeview() + messagebox.showinfo("Sucesso", "Pessoa apagada com sucesso.") \ No newline at end of file diff --git a/visao/frames/frame_pet.py b/visao/frames/frame_pet.py new file mode 100644 index 0000000..3e5906e --- /dev/null +++ b/visao/frames/frame_pet.py @@ -0,0 +1,125 @@ +import tkinter as tk +from tkinter import ttk, messagebox + +from modelo.pet import Pet +from visao.componentes.dialogo_adicionar_pet import DialogoAdicionarPet + +class FramePet(tk.Frame): + def __init__(self, master=None, bd=None): + super().__init__(master, bg="#1e1e1e") + self.bd = bd + self._criar_layout() + + def _criar_layout(self): + # Título da seção + titulo_label = tk.Label( + self, + text="GERENCIAR PETS", + font=("Arial", 24, "bold"), + bg="#1e1e1e", + fg="white" + ) + titulo_label.pack(pady=20) + + # Estilo para a Treeview + style = ttk.Style() + style.theme_use("default") + style.configure("Treeview", + background="#2c2c2c", # Cor de fundo da Treeview + foreground="white", + rowheight=25, # Altura da linha + fieldbackground="#2c2c2c", + bordercolor="#2c2c2c", + borderwidth=0) + style.map('Treeview', background=[('selected', '#1f6aa5')]) + + style.configure("Treeview.Heading", + background="#2c2c2c", + foreground="white", + font=("Arial", 12, "bold"), + relief="flat") + style.map("Treeview.Heading", + background=[('active', '#3c3c3c')]) + + # Frame para a Treeview e Scrollbar + tree_container = tk.Frame(self, bg="#1e1e1e") + tree_container.pack(pady=10, padx=20, fill="both", expand=True) + + self.tree = ttk.Treeview(tree_container, columns=("id", "nome", "especie"), show="headings") + self.tree.heading("id", text="ID") + self.tree.heading("nome", text="Nome", anchor="w") + self.tree.heading("especie", text="Espécie", anchor="w") + + self.tree.column("id", width=100, anchor="center", stretch=tk.NO) + self.tree.column("nome", stretch=tk.YES) + self.tree.column("especie", stretch=tk.YES) + + scrollbar = ttk.Scrollbar(tree_container, orient="vertical", command=self.tree.yview) + self.tree.configure(yscrollcommand=scrollbar.set) + + self.tree.pack(side="left", fill="both", expand=True) + scrollbar.pack(side="right", fill="y") + + self.popular_treeview() + + # Frame para os botões de ação + botoes_frame = tk.Frame(self, bg="#1e1e1e") + botoes_frame.pack(pady=10, padx=20, fill="x") + + # Botão Adicionar + btn_adicionar = tk.Button( + botoes_frame, + text="Adicionar", + command=self.adicionar_pet, + bg="#4CAF50", + fg="white", + font=("Arial", 12), + relief="flat", + padx=10, + pady=5 + ) + btn_adicionar.pack(side="left", padx=5) + + # Botão Apagar + btn_apagar = tk.Button( + botoes_frame, + text="Apagar", + command=self.apagar_pet, + bg="#f44336", + fg="white", + font=("Arial", 12), + relief="flat", + padx=10, + pady=5 + ) + btn_apagar.pack(side="left", padx=5) + + def popular_treeview(self): + for i in self.tree.get_children(): + self.tree.delete(i) + for pet in self.bd.pets.listar_todos(): + self.tree.insert("", "end", values=(pet.id, pet.nome, pet.especie)) + + def adicionar_pet(self): + dialog = DialogoAdicionarPet(self) + if dialog.result: + nome = dialog.result["nome"] + especie = dialog.result["especie"] + proximo_id = self.bd.obter_proximo_id() + novo_pet = Pet(proximo_id, nome, especie) + self.bd.pets.inserir(novo_pet) + self.popular_treeview() + messagebox.showinfo("Sucesso", "Pet adicionado com sucesso.") + + def apagar_pet(self): + selecionado = self.tree.selection() + if not selecionado: + messagebox.showwarning("Aviso", "Por favor, selecione um pet para apagar.") + return + + item = self.tree.item(selecionado[0]) + id_pet, nome_pet, _ = item['values'] # Ignora a espécie, que agora está na treeview + if messagebox.askyesno("Confirmar", f"Tem certeza que deseja apagar '{nome_pet}'?"): + self.bd.pets.remover(id_pet) + self.popular_treeview() + messagebox.showinfo("Sucesso", "Pet apagada com sucesso.") \ No newline at end of file diff --git a/visao/tela_principal.py b/visao/tela_principal.py index 4a77a89..959b7f1 100644 --- a/visao/tela_principal.py +++ b/visao/tela_principal.py @@ -17,11 +17,11 @@ class TelaPrincipal(tk.Tk): self.configure(bg="#1e1e1e") self.bd = BancoDeDados() - if not self.bd.pessoas.listar_todos(): # Adiciona apenas se estiver vazio - self.bd.pessoas.inserir(Pessoa(1, "Ana Silva")) - self.bd.pessoas.inserir(Pessoa(2, "Bruno Costa")) - self.bd.pessoas.inserir(Pessoa(3, "Carlos Dias")) - self.bd.pessoas.inserir(Pessoa(4, "Daniel Santos")) + # if not self.bd.pessoas.listar_todos(): # Adiciona apenas se estiver vazio + # self.bd.pessoas.inserir(Pessoa(1, "Ana Silva")) + # self.bd.pessoas.inserir(Pessoa(2, "Bruno Costa")) + # self.bd.pessoas.inserir(Pessoa(3, "Carlos Dias")) + # self.bd.pessoas.inserir(Pessoa(4, "Daniel Santos")) self.header = tk.Frame(self, bg="#2c2c2c", height=80) @@ -55,7 +55,8 @@ class TelaPrincipal(tk.Tk): botoes = [ ("Início", self.mostrar_inicio), ("Pessoas", self.mostrar_pessoas), - ("Pets", self.mostrar_inicio), + ("Pets", self.mostrar_pet), + ("Adoções", self.mostrar_adocoes), ("Sair", self.sair), ] @@ -95,6 +96,18 @@ class TelaPrincipal(tk.Tk): frame = FramePessoas(self.area_conteudo, self.bd) frame.pack(expand=True, fill="both") + def mostrar_pet(self): + from visao.frames.frame_pet import FramePet + self.limpar_conteudo() + frame = FramePet(self.area_conteudo, self.bd) + frame.pack(expand=True, fill="both") + + def mostrar_adocoes(self): + from visao.frames.frame_adocao import FrameAdocao + self.limpar_conteudo() + frame = FrameAdocao(self.area_conteudo, self.bd) + frame.pack(expand=True, fill="both") + def limpar_conteudo(self): for widget in self.area_conteudo.winfo_children(): widget.destroy()