Tutorial: Aplicação em Python + SQLite (Parte 03)

Tutorial: Aplicação em Python + SQLite (Parte 03)

Overview

Bem-vindos à terceira parte do nosso tutorial, onde mergulhamos de cabeça na aventura de ligar o backend ao frontend de nossa aplicação Python! Com passos bem humorados, porém focados, vamos transformar duas peças independentes em um conjunto harmonioso. Se você já acompanhou as etapas anteriores, prepare-se para a mágica acontecer. Se não, ainda está em tempo de se juntar a nós! Rode as mangas, pois hoje é dia de fazer nossa interface gráfica ganhar vida e responder aos seus comandos.

Durante a primeira e a segunda partes deste tutorial, fizemos a interface gráfica e todos os comportamentos que serão necessários para a aplicação funcionar. Agora precisamos ligar a interface (gui.py) aos comportamentos definidos (backend.py). Da forma que fizemos, ambas partes são independentes. A interface gráfica pode ser utilizada de várias formas e as funções de acesso ao banco podem ser utilizadas via script, sem necessidade de uma parte gráfica…

Índice:

Parte 03_ Ligando o Backend com o Frontend;

A primeira coisa que devemos fazer é criar outro arquivo, este deverá ser chamado de Aplicacao.py. Nele, vamos importar as duas outras camadas que criamos e declarar uma variável chamada app.

from GUI import *
import Backend as core

app = None

Acima, fizemos as importações de duas maneiras diferentes. Na segunda importação, demos um “apelido” para o script Backend. Esta prática pode ajudar a organizar as importações.

Agora vamos instanciar a variável app que foi criada no passo anterior…

app = Gui()

Não é necessária a utilização da keyword new. Agora esta variável é uma instancia da classe Gui e contem a janela e todos os elementos dela. Bom, o próximo passo é associar os comportamentos à interface….

app.btnViewAll.configure(command=view_command)
app.btnBuscar.configure(command=search_command)
app.btnInserir.configure(command=insert_command)
app.btnUpdate.configure(command=update_command)
app.btnDel.configure(command=del_command)
app.btnClose.configure(command=app.window.destroy)

No fonte acima utilizamos, utilizamos a variável app para acessar os elementos que definimos para a janela. Para fazer a ligação, utilizamos a função configure, passando o argumento e o nome de uma função.

As funções passadas no command (view_command, search_command, etc…) ainda não existem, mas elas são necessárias, pois existe uma pegadinha aqui: O parâmetro command recebe as funções, mas estas não podem ter argumentos… e nós precisaremos dele. Na medida em que criamos estas funções de comando, este ponto ficará mais claro.

A primeira função de comando será a de visualização dos resultados (view_command):

def view_command():
    rows = core.view()
    app.listClientes.delete(0, END)
    for r in rows:
        app.listClientes.insert(END, r)

Neste comando, realizamos as seguintes ações:

  • utilizamos a função view() do Backend para recuperar os dados;
  • limpamos a listbox de clientes;
  • fazemos uma iteração pelo resultado, adicionando as linhas a listbox de clientes.

Tanto nos comandos de insert quanto no de delete da listbox foi utilizado a keyword END, ela é uma constante do Python que sempre aponta para última posição do listbox.

A próxima função será a de busca (search_command):

def search_command():
    app.listClientes.delete(0, END)
    rows = core.search(app.txtNome.get(), app.txtSobrenome.get(), app.txtEmail.get(), app.txtCPF.get())
    for r in rows:
        app.listClientes.insert(END, r)

Nesta função, também limpamos a listbox de clientes e depois chamamos a função search do backend, passando os valores das variáveis que estão com o bind nos campos de input (entry). Se estiver com dúvidas sobre esta configuração, acesse novamente a primeira parte deste tutorial. O método .get() é necessário, pois as variáveis estão recebendo um objeto do campo de input (entry), ele é algo parecido com o .ToString() do C#.

O próximo comando é o de inserção de dados (insert_command):

def insert_command():
    core.insert(app.txtNome.get(), app.txtSobrenome.get(), app.txtEmail.get(), app.txtCPF.get())
    view_command()

A única coisa diferente que fizemos nesta função foi chamado o comando de visualização de todos os registros, para que o usuário consiga ver o Cliente que acabou de adicionar.

No momento, se o usuário clicar em algum dos itens da listbox, nada irá acontecer. Isso implica em dizer que não é possível editar ou excluir um registro. Agora precisamos fazer uma função que pegue o valor selecionado na listbox e popule os campos de input.

def getSelectedRow(event):
    global selected
    index = app.listClientes.curselection()[0]
    selected = app.listClientes.get(index)
    app.entNome.delete(0, END)
    app.entNome.insert(END, selected[1])
    app.entSobrenome.delete(0, END)
    app.entSobrenome.insert(END, selected[2])
    app.entEmail.delete(0, END)
    app.entEmail.insert(END, selected[3])
    app.entCPF.delete(0, END)
    app.entCPF.insert(END, selected[4])

Nesta função, a primeira coisa feita foi declarar uma variável que pode ser acessada de qualquer lugar do script. Boas práticas ditam que não se deve declarar uma variável global de dentro de uma função, mas para demonstrar que isso é possível fiz desta forma.

Na sequência, realizamos as seguintes ações:

  • Recuperamos o index do item selecionado. (Este index é a primeira posição do vetor retornado pela função curselection()).;
  • Armazenamos o item selecionado na variável global selected;
  • Na sequência, vamos sistematicamente apagando e preenchendo novamente os campos de input (entry);

O próximo passo é associar esta função ao listbox e isso é um pouco diferente do que foi feito com os outros elementos (widgets).

app.listClientes.bind('<<ListboxSelect>>', getSelectedRow)

No fonte acima definimos (bind) que, sempre que um item for selecionado (<<ListboxSelect>>), a função getSelectedRow será disparada.

Agora já é possível criar as funções de atualização e exclusão. Vamos começar pela de atualização (update_command):

def update_command():
    core.update(selected[0],app.txtNome.get(),app.txtSobrenome.get(),app.txtEmail.get(), app.txtCPF.get())
    view_command()

A lógica desta função é bem similar a de inserção de dados, mas ela precisa de um argumento a mais, do id e este valor é a primeira posição do vetor que armazena o item selecionado (variável selected). Para os outros campos, não vamos utilizar o que está armazenado na variável select, pois queremos atualizar os valores daquele registro e a variável está com os valores originais. Por isso utilizamos os valores dos campos de input (entry).

O último comando é o de exclusão e é o mais simples dos 5…

def del_command():
    id = selected[0]
    core.delete(id)
    view_command()

Estamos quase no final da aplicação. Precisamos de mais um comando, o que inicia o loop principal da janela.

app.run()

Sugiro reorganizar o código, deixando o fonte deste arquivo na seguinte ordem:

  • Importação da parte gráfica e do backend;
  • Declaração da variável app (app = None);
  • Declaração das funções de comando (view_command, search_command, insert_command, etc);
  • Declaração da função getSelectedRow;
  • Instanciação da variável app (app = Gui());
  • Bind da listbox (app.listClientes.bind…);
  • Associação das funções de comando aos objetos (app.btnViewAll.configure…)
  • Função de inicialização da janela (app.run())

A aplicação agora está pronta. Basta executar o script Aplicacao.py que a janela será exibida.

Imagino que você não queira distribuir sua aplicação no formato de script e a próxima parte deste tutorial vai cuidar disso.

Postagens nesta série