Criado o banco de dados, as telas, vamos abrir nossa IDE e programar. Vamos então começar pelo arquivo que contém a nossa classe main, e através dele que vamos dar o "play" na nossa aplicação, o que pode também ser feito através de comandos no Terminal, por exemplo. Para rodar a aplicação então podemos executar o comando:
# python gfp.py
Ou então podemos dar permissão de execução ao nosso arquivo (como fazemos com arquivos shell-script):
# chmod +x gfp.py
E assim executamos apenas com o comando:
# ./gfp.py
Mas antes disso temos que programar, antão vamos voltar. Eu tenho por costume sempre comentar bastante meus códigos-fonte, e como vou passar os códigos do exemplo na íntegra os meus comentários ajudaram a compreender melhor o que fazemos. Ah, sim, caso haja algum problema com os códigos pode ser culpa de conflitos com a formatação do HTML, principalmente pra identação, então, a exemplo dos arquivos ".glade", eu estou disponibilizando os códigos no meu site em:
Arquivo: gfp.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
#Importação das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
#Usando arquivos do projeto
import usuarioslista
import funcoes as f
import usuarioscadastro
class Programa(gtk.Window):
#Método construtor
def __init__(self):
#Variável de controle do login
self.matarprograma = 0;
#Inicializa
super(Programa, self).__init__()
#Carrega arquivo glade
self.GLADE_FILE = f.CaminhoGlade + 'gfp.glade'
gui = glade.XML(self.GLADE_FILE, 'winGFP')
#Associa os controles
self.mnUsuarios = gui.get_widget('mnUsuarios')
self.mnSair = gui.get_widget('mnSair')
self.mnSobre = gui.get_widget('mnSobre')
self.win = gui.get_widget('winGFP')
self.stbStatus = gui.get_widget('stbStatus')
#Associa eventos dos controles
self.mnUsuarios.connect('activate', usuarioslista.UsuariosLista)
self.mnSair.connect('activate', self.Sair, None)
self.mnSobre.connect('activate', self.MostraSobre)
self.win.connect('delete_event', self.Sair)
self.win.connect('show', self.MostraLogin)
#Início do programa
self.win.show_all()
#Verifica login
if self.matarprograma == 0:
#Coloca dados do usuário na barra de status
self.stbStatus.push(0, ' Usuário: ' + str(f.usuariologadoid) + ' - [' + f.usuariologadouser + '] ' + f.usuariologadonome)
else:
#Abre o programa mas deixa tudo inativo
self.mnUsuarios.set_sensitive(False)
f.Mensagem(self.win, "Voc? não está logado.")
self.stbStatus.push(0, ' Você não está logado.')
#Fechar conexões e sair
def Sair(self, widget, event):
if self.matarprograma == 0:
if f.MsgConfirmacao(self.win, 'Deseja realmente sair do GFP?'):
f.cnx.close()
gtk.main_quit()
return False
else:
return True
else:
f.cnx.close()
gtk.main_quit()
return False
#Abre janela sobre o programa
def MostraSobre(self, widget):
guiSobre = glade.XML(self.GLADE_FILE, 'winSobre')
winSobre = guiSobre.get_widget('winSobre')
winSobre.run()
winSobre.destroy()
#Abre tela de login
def MostraLogin(self, widget):
T = 0
while T == 0:
#Carrega tela do arquivo glade
guiLogin = glade.XML(self.GLADE_FILE, 'winLogin')
#Associa os controles
winLogin = guiLogin.get_widget('winLogin')
edtUsuario = guiLogin.get_widget('edtUsuario')
edtSenha = guiLogin.get_widget('edtSenha')
btnNewUser = guiLogin.get_widget('btnNovoUser')
lblTitulo = guiLogin.get_widget('lblEntrar')
#Formata controles
lblTitulo.set_markup("Entrar no GFP")
lblTitulo.set_justify(gtk.JUSTIFY_LEFT)
def AbreCadastroUsu(widget):
try:
usuarioscadastro.UsuariosCadastro(widget, True, 0, winLogin, self)
winLogin.set_focus(edtUsuario)
except:
pass
#Associa eventos
edtUsuario.connect("changed", lambda *a: f.StrToMais(edtUsuario))
edtSenha.connect("changed", lambda *a: edtSenha.set_text(f.TiraAspa(edtSenha.get_text())))
edtUsuario.connect("focus_out_event", lambda *a: f.StrToTrim(edtUsuario))
btnNewUser.connect("clicked", AbreCadastroUsu)
#Abre a janela
self.matarprograma = winLogin.run()
#Inverte valores
if self.matarprograma == 0:
self.matarprograma = -1
else:
self.matarprograma = 0
#Fecha janela sem verificação
if self.matarprograma == -1:
T = 1
#Verifica dados digitados
if (edtUsuario.get_text() != '' and edtSenha.get_text() != '') or self.matarprograma == -1:
if self.matarprograma != -1:
#Verifica usuário no banco
f.query.execute("SELECT id, user, nome FROM usuarios WHERE\
user = '" + edtUsuario.get_text() + "' and\
senha = '" + edtSenha.get_text() + "'")
T = 0
for row in f.query:
#Usuário encontrado
f.usuariologadoid = row[0]
f.usuariologadouser = row[1]
f.usuariologadonome = row[2]
T = 1
if T == 0:
f.Mensagem(winLogin, 'Usuário ou senha inválidos!')
else:
T = 1
else:
f.Mensagem(winLogin, 'Você deve informar o usuário e a senha!')
winLogin.destroy()
Programa()
gtk.main()
Explicando um pouco o que foi feito, no início do arquivo temos um bloco onde importamos as bibliotecas que vamos usar (banco de dados, parte gráfica) e vinculamos os arquivos de dentro do projetos que usamos e "chamamos" nesta classe:
#Importação das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
#Usando arquivos do projeto
import usuarioslista
import funcoes as f
import usuarioscadastro
Em seguida iniciamos a criação da classe com seu método construtor. Tanto as instruções acima quanto as que se seguem são praticamente o modelo de como fazemos em todos os nossos arquivos de classe:
class Programa(gtk.Window):
#Método construtor
def __init__(self):
#Variável de controle do login
self.matarprograma = 0;
#Inicializa
super(Programa, self).__init__()
Note a identação, em todo o código vamos como ela funciona conforma o que eu disse no início, delimitando blocos. Outro ponto que já podemos considerar é a palavra def - é com ela que definimos as funções. As instruções que se segum depois disso é aquilo que vai ser executado cronologicamente quando o arquivo for instanciado e chamado. Indo até o fim do arquivo, vemos duas instruções que fazem com que a classe se auto-instancie e se auto execute quando executarmos o arquivo. É assim que definimos o main no Python:
Programa()
gtk.main()
Voltando ao início do arquivo, logo após o segundo bloco que eu detalhei na explicação, vamos as instruções que leem o arquivo ".glade" e associa cada controle colocado e nomeado neste neste arquivo a uma variável/propriedade da nossa classe. Em seguida associamos eventos aos controles, como clique, foco etc.
#Carrega arquivo glade
self.GLADE_FILE = f.CaminhoGlade + 'gfp.glade'
gui = glade.XML(self.GLADE_FILE, 'winGFP')
#Associa os controles
self.mnUsuarios = gui.get_widget('mnUsuarios')
self.mnSair = gui.get_widget('mnSair')
self.mnSobre = gui.get_widget('mnSobre')
self.win = gui.get_widget('winGFP')
self.stbStatus = gui.get_widget('stbStatus')
#Associa eventos dos controles
self.mnUsuarios.connect('activate', usuarioslista.UsuariosLista)
self.mnSair.connect('activate', self.Sair, None)
self.mnSobre.connect('activate', self.MostraSobre)
self.win.connect('delete_event', self.Sair)
self.win.connect('show', self.MostraLogin)
O resto é normal. Prestando atenção na identação do arquivo vemos as funções serem criadas, enfim, uma espécie de estrutura procedural. Só um detalhe que aparece pela primeira vez na função MostraLogin, um tal de "lambda *a:" na associação de uma função ao evento de um controle: isso é uma espécie de call, usado geralmente para chamar funções de outra classe ou arquivo dentro da nossa classe.