Sei sulla pagina 1di 23

Desenvolvendo aplicaes GUI simples em Python & Gla...

1 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

Desenvolvendo aplicaes GUI simples em Python & Glade (PyGTK)


com banco de dados SQLite
Autor: Pedro Arajo <pedro-araujo at pedro-araujo.com>
Data: 28/07/2010
Introduo
Desde que eu mudei pro GNU/Linux que tenho buscado a melhor alternativa para
desenvolver minhas aplicaes. Como eu vinha de muito tempo trabalhando e
programando com e para Windows (infelizmente), naturalmente tudo o que eu fazia no
Linux eu procurava fazer sempre da maneira mais semelhante ao que eu faria no
Windows, e com a programao no foi diferente.
No Windows, por um longo tempo eu trabalhei com Visual Basic, mas sempre fui f do
Delphi, ento meu primeiro impulso ao vir pro Linux foi usar o Lazarus (conra meu
post sobre isso em meu blog), e por mais que ele seja uma tima ferramenta, eu no
me senti muito vontade com ele, alguns bugs e incompatibilidades acabaram me
desanimando.
Depois eu ca no C++, (primeiro com GTK e depois com QT), me empolguei bastante
no incio (tambm escrevi sobre isso em meu blog), mas a "burocracia" e a
complicao dessa linguagem tambm me desencorajaram, no porque a linguagem
no seja boa, mas porque eu queria algo mais simples mesmo. Ah, sim, eu at cheguei
a tentar algo com o Gambas, uma IDE para Basic (veja neste post), s que isso no
passou de curiosidade.
Enm, foram vrias tentativas improdutivas, mesmo assim eu ainda "torcia o nariz"
pro Python - o artigo "Python em 15 minutos" do Wiki Ubuntu-BR (minha distribuio
principal) at que chamava minha ateno, porm demorou pra eu ter interesse em ir
mais a fundo.
A primeira vez em que ouvi falar em Python foi em 2003, quando eu nem cogitava
abraar a causa GNU/Linux, foi atravs de um colega de trabalho que comentou sobre
um ex-colega dele: "o cara era meio louco, programava em Python". Anedotas parte,
um dos motivos que me levou a relutar diante do Python o mesmo que hoje me
impulsiona a escrever sobre o assunto.
Por mais que seja uma linguagem amplamente usada no mundo Linux, principalmente
no Ubuntu, ainda existe uma certa diculdade de encontrar materiais que abordem o
assunto de maneira objetiva no nosso idioma (Portugus) - existe sim muita coisa boa a

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

2 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

respeito em Ingls, mesmo assim (pelo menos eu vejo assim) se voc zer uma
pesquisa no Google dicilmente vai achar um "HowTo" simples e direto, a maioria das
apostilas e tutoriais se limitam ao bsico do bsico, e quando achamos algo, digamos,
mais produtivo, sempre tudo muito fragmentado.
Outro aspecto, isso principalmente pra quem j tinha uma certa experincia em outras
linguagens e plataformas como eu, que, num primeiro momento, olhar para um
cdigo Python algo que chega a ser meio estranho, ele parece ser diferente de tudo o
que j vimos, a sintaxe, o modo de programar em si, sem contar que uma das poucas
linguagens (na verdade nesse sentido eu s conheo Python mesmo) em que a
identao inuencia no processamento dos algortimos, principalmente no que se
refere delimitao dos blocos de instrues, como if, for, while, try e na "hierarquia"
de funes e classes... Isso tudo uma coisa que pode se reverter radicalmente (e
positivamente) com o tempo, e principalmente com o interesse que surge depois que o
preconceito derrubado - foi o meu caso.

Por que Python?


Depois que a gente passa a conhecer a tecnologia podemos entender as suas
vantagens e superar as diculdades de maneira mais fcil. Indo aos porqus, o
primeiro que Python literalmente usado pra fazer quase tudo no Ubuntu (e na
maioria dos Debian-like, e creio eu que nas distros de outras vertentes tambm seja
mais ou menos assim, mas no conheo, pois fora o Kurumin, Ubuntu (e seus variantes
Kubuntu e Lubuntu) e Debian, das demais distros eu mexi bem pouco com o Fedora e
nada mais), desde gadgets da rea de trabalho at importantes e complexas
ferramentas de sistema, sempre tem um arquivo ".py" em cena.
Em segundo vem uma consequncia dessa ampla adoo do Python pelas
distribuies, que o suporte nativo, como o caso do Ubuntu, a essa tecnologia - com
raras excees, s fazer um script Python e rodar, como se fosse um shell-script.
Como presumo que vocs j saibam, o Python uma linguagem interpretada, pode at
ser compilada, mas a maioria das aplicaes desenvolvidas nela so distribudas na
forma do arquivo-fonte mesmo (o que bem bvio j que estamos no contexto
GNU/Linux, software livre, open source...) e por isso voc no vai precisar instalar
nenhum pacote a mais na hora de desenvolver sua aplicaes, tampouco na hora de
distribu-las.
Por m, leveza e simplicidade so um dos aspectos que no meu caso, depois, repito, de
estudar um pouco e entender melhor o sentido das coisas, so vantagens em relao a
tudo o que eu j procurei nesse sentido - resumindo, pra desenvolver suas aplicaes,
Python pode ser uma alternativa muito fcil e rpida, sem deixar de ser poderosa.
Pra concluir eu gostaria de dizer tambm o porqu do Glade e o porqu do SQLite.
Bem, so praticamente os mesmos argumentos que eu usei sobre o Python no m do
pargrafo anterior. Glade porque temos uma ferramenta muito simples pra desenhar
as telas em modo grco na base do "arrastar e soltar", porque ele trabalha sobre a

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

3 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

biblioteca GTK (que a biblioteca grca do GNOME, ambiente grco do Ubuntu e


Debian, mas que tambm est disponvel para outros ambientes como o KDE), porque
leve... SQLite porque o mais indicado como banco de dados pra aplicaes desktop
locais (navegadores como o Firefox, Chrome e Opera usam ele), simples e leve... E
como provavelmente voc j esteja usando estes recursos em outras aplicaes que
voc tenha instalado ou que j vieram com a sua distribuio, voc no vai precisar
instalar mais nada tambm. E, antes que eu me esquea, suas aplicaes
desenvolvidas usando esse trio podem ser facilmente portadas para outras
plataformas, incluindo Windows.

Preparando o ambiente
Como eu disse, Python muito simples e leve. Voc pode escrever seus programas
Python em um editor de texto simples, e caso voc escolha o Gedit do GNOME ainda
tem o recurso syntax-highlighter que ajuda bastante. Mas existem vrias IDE's para
Python, como Eric, IDLE, o prprio Anjuta e uma das mais populares, o Eclipse - como
bem sabemos o Eclipse uma IDE multiplataforma e multilinguagem, e se voc j tem
instalado o Eclipse basta instalar um plugin pra Python.
Mas eu gostaria de destacar aqui uma alternativa interessante, baseada no Eclipse, o
Easy Eclipse for Python, que a IDE que eu uso - este projeto Easy Eclipse
disponibiliza distribuies compactas do Eclipse voltadas e otimizadas pra uma
linguagem especca cada, basta baixar o arquivo pelo link no site do projeto,
descompactar onde voc achar melhor e clicar no arquivo executvel (ele est
disponvel tanto pra Linux, quanto pra Windows e Mac OS X).
Usar uma IDE agiliza bastante nosso trabalho, e no caso do Easy Eclipse s baixar,
descompactar e usar - a menos que voc precise fazer alguma adequao especca
em seu sistema nada precisa ser congurado, s programar e dar "play".
Para "desenhar" as nossas telas usamos o Construtor de Interfaces Glade, que de
fcil instalao, nenhuma novidade, facilmente encontrado na Central de Programas
do Ubuntu, ou no Adicionar/Remover Aplicaes do Debian, ou ento voc pode
instalar diretamente o pacote glade-gnome pelo Synaptic ou via apt-get - instalar
fcil, falar disso aqui chega a ser "chover no molhado".
Pra criar e manusear nosso banco de dados SQLite que usaremos na aplicao minha
dica usar o Sqliteman, que est l na Central de Programas do Ubuntu, ou ento
procure pelo pacote sqliteman e instale conforme a disponibilidade dele para sua
distribuio - um detalhe que no menu Aplicativos este aplicativo no ca na
categoria Desenvolvimento, mas sim em Escritrio.
Tendo instalado estes trs programas que precisamos, mais especicamente os ltimos
dois, creio eu que junto com eles todas as dependncias e pacotes necessrios j tero
sido instalados junto no processo (pelo menos comigo foi assim). Caso seu sistema
acuse a falta de algum componente verique a instalao dos seguintes pacotes (no

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

4 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

necessariamente nesta mesma ordem):

Python
python (geralmente basta pedir pra instalar este pacote que o resto vem junto,
mas quase impossvel que voc j no tenha instalado ele)
python-minimal
python-dev
python2.6-dev
python2.6-minimal

GTK/Glade
glade-gnome (geralmente basta pedir pra instalar este pacote que o resto vem
junto)
glade
libglade2-0
libglade2-dev
libgtk2.0-0
libgtk2.0-dev
python-glade2
python-gtk2
python-gtk2-dev

SQLite
sqlite3 (a instalao geralmente no necessria pois o SQLite foi feito pra
funcionar com o arquivo sozinho, sem precisar de componentes adicionais, pelo
menos pras aplicaes cliente - este pacote disponibiliza uma interface de linha
de comando pra manusear seus bancos de dados)
python-pysqlite2 (sequer tenho instalada)
A lista parece grande, mas s por garantia, pra poupar tempo caso algo no funcione
direito, mas eu no acredito que isso possa acontecer, pois, como destaquei, falando do
Ubuntu principalmente, ele d pleno suporte pro Python, ento o risco quase
inexistente.
Bem, e j que estamos nos prevenindo contra possveis falhas causadas por falta de
pacotes ou congurao, caso seu Easy Eclipse no consiga dar o "play" no seu
21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

5 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

programa, nele, v em Window - Preferences..., selecione e abra o item PyDev na lista,


depois o subitem Interpreter - Python e informe o caminho /usr/bin/python - fazendo
isso as bibliotecas necessrias sero adicionadas automaticamente e tudo vai
funcionar, mas eu realmente creio que no seja necessrio pois no meu caso tudo foi
congurado automaticamente (isso pode mudar dependendo de sua distro ou se voc
estiver usando Windows, por exemplo).
E isso.

Dando forma aplicao

Banco de dados
Primeiro vamos criar o nosso banco de dados de exemplo. Bem, eu no vou explicar
como usar o Sqliman, ele uma ferramenta de manipulao de banco de dados bem
simples e intuitiva, e se voc est lendo este artigo, creio que tenha conhecimento
suciente para faz-lo, seria redundncia. Nesse nosso exemplo eu vou usar parte de
um aplicativo que estou fazendo pra controlar minhas despesas pessoais, do meu jeito.
O objetivo deste artigo mostrar de forma objetiva como realizar procedimentos
bsicos de programao, ento vamos abordar a criao da parte grca do programa,
vamos falar de como usar controles e eventos simples na nossa aplicao, como
botes, caixas de textos, janelas, dilogos, listas, o bsico necessrio da linguagem
Python e como fazer as principais operaes com banco de dados como SELECT,
INSERT, UPDATE e DELETE. Vou usar a tabela de usurios da minha aplicao como
base do exemplo, vamos cadastrar, vericar login, listar, alterar dados e excluir. Enm,
nossa tabela no banco ser criada assim:
CREATE TABLE "usuarios" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
"user" VARCHAR(20) NOT NULL,
"nome" VARCHAR(50) NOT NULL,
"senha" VARCHAR(8) NOT NULL
);
Voc pode criar, salvar e executar seus arquivos onde quiser, tando os ".glade" da
parte grca, quanto o nosso ".sqlite" do banco e os ".py" do programa - pra encurtar
caminho, pro meu projeto eu criei uma pasta /opt/gfpopen/ e estou trabalhando nela.

Telas
Criar a parte grca do programa usando o Glade a melhor opo na minha opinio.
21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

6 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

Voc pode criar suas telas "no brao", programando linha por linha pra criar,
posicionar, organizar e formatar os controles, mas isso d muito mais trabalho do que
"arrastar e soltar". ento vamos criar no nosso exemplo as telas no Glade que ele vai
salvar com a extenso ".glade" (que na verdade um arquivo XML) e ento ns
"lemos" este arquivo com alguns poucos comandos usando as funes das bibliotecas
do Python e ele monta as telas pra ns.
Bem, eu tambm no vou me aprofundar no Glade, j z isso de certa forma em artigos
anteriores, conforme voc pode conferir nos links que coloquei na introduo deste
artigo. Os arquivos das telas so pequenos em questo de bytes, mas como so
arquivos XML o texto do cdigo-fonte deles um pouco extenso, ca maio invivel
colocar linha por linha aqui, ento eu estou disponibilizando os arquivos e as imagens
que eu usei pra criao da parte grca deste exemplo num diretrio no meu site,
pode acessar l e ver sem medo:
http://pedro-araujo.com/arquivos/ex-py/
Ns podemos criar um arquivo ".glade" pra cada tela da nossa aplicao, mas eu
preferi agrupar por mdulos - neste exemplo no arquivo gfp.glade eu "desenhei" a tela
principal, o dilogo de login e coloquei a janela com o sobre; no arquivo
usuarioslista.glade est a tela de listagem e a de cadastro dos usurios. Basta voc
baixar os arquivos e abrir no Glade que visualmente vai car bem fcil entender, bem
parecido com o que fazemos com HTML.

Agora vamos programar


Criado o banco de dados, as telas, vamos abrir nossa IDE e programar. Vamos ento
comear pelo arquivo que contm a nossa classe main, e atravs dele que vamos dar o
"play" na nossa aplicao, o que pode tambm ser feito atravs de comandos no
Terminal, por exemplo. Para rodar a aplicao ento podemos executar o comando:
# python gfp.py
Ou ento podemos dar permisso de execuo ao nosso arquivo (como fazemos com
arquivos shell-script):
# chmod +x gfp.py
21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

7 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

E assim executamos apenas com o comando:


# ./gfp.py
Mas antes disso temos que programar, anto vamos voltar. Eu tenho por costume
sempre comentar bastante meus cdigos-fonte, e como vou passar os cdigos do
exemplo na ntegra os meus comentrios ajudaram a compreender melhor o que
fazemos. Ah, sim, caso haja algum problema com os cdigos pode ser culpa de
conitos com a formatao do HTML, principalmente pra identao, ento, a exemplo
dos arquivos ".glade", eu estou disponibilizando os cdigos no meu site em:
http://pedro-araujo.com/arquivos/ex-py/src/
Arquivo: gfp.py
#!/usr/bin/python
# -*- coding: utf-8 -*#Importao 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):
#Mtodo construtor
def __init__(self):
#Varivel 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')
21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

8 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

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)
#Incio do programa
self.win.show_all()
#Verica login
if self.matarprograma == 0:
#Coloca dados do usurio na barra de status
self.stbStatus.push(0, ' Usurio: ' + 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? no est logado.")
self.stbStatus.push(0, ' Voc no est logado.')

#Fechar conexes e sair


def Sair(self, widget, event):
if self.matarprograma == 0:
if f.MsgConrmacao(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()

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

9 de 23

http://www.vivaolinux.com.br/artigos/impressora.php?co...

#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 vericao
if self.matarprograma == -1:
T=1
#Verica dados digitados

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

if (edtUsuario.get_text() != '' and edtSenha.get_text() != '') or self.matarprograma


== -1:
if self.matarprograma != -1:
#Verica usurio 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:
#Usurio encontrado
f.usuariologadoid = row[0]
f.usuariologadouser = row[1]
f.usuariologadonome = row[2]
T=1
if T == 0:
f.Mensagem(winLogin, 'Usurio ou senha invlidos!')
else:
T=1
else:
f.Mensagem(winLogin, 'Voc deve informar o usurio e a senha!')
winLogin.destroy()

Programa()
gtk.main()
Explicando um pouco o que foi feito, no incio do arquivo temos um bloco onde
importamos as bibliotecas que vamos usar (banco de dados, parte grca) e
vinculamos os arquivos de dentro do projetos que usamos e "chamamos" nesta classe:
#Importao 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 criao da classe com seu mtodo construtor. Tanto as
instrues acima quanto as que se seguem so praticamente o modelo de como
fazemos em todos os nossos arquivos de classe:

10 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

class Programa(gtk.Window):
#Mtodo construtor
def __init__(self):
#Varivel de controle do login
self.matarprograma = 0;
#Inicializa
super(Programa, self).__init__()
Note a identao, em todo o cdigo vamos como ela funciona conforma o que eu disse
no incio, delimitando blocos. Outro ponto que j podemos considerar a palavra def com ela que denimos as funes. As instrues que se segum depois disso aquilo
que vai ser executado cronologicamente quando o arquivo for instanciado e chamado.
Indo at o m do arquivo, vemos duas instrues que fazem com que a classe se
auto-instancie e se auto execute quando executarmos o arquivo. assim que denimos
o main no Python:
Programa()
gtk.main()
Voltando ao incio do arquivo, logo aps o segundo bloco que eu detalhei na
explicao, vamos as instrues que leem o arquivo ".glade" e associa cada controle
colocado e nomeado neste neste arquivo a uma varivel/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 ateno na identao do arquivo vemos as funes serem
criadas, enm, uma espcie de estrutura procedural. S um detalhe que aparece pela
primeira vez na funo MostraLogin, um tal de "lambda *a:" na associao de uma
funo ao evento de um controle: isso uma espcie de call, usado geralmente para

11 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

chamar funes de outra classe ou arquivo dentro da nossa classe.

Continuando a programar
Como vimos nosso arquivo principal usa outros arquivos do projeto, claro. Estes
arquivos seguem o mesmo modelo, com exceo do funcoes.py que no dene
nenhuma classe, apenas, como o nome j diz, tem funes e variveis que usaremos
globalmente no aplicativo. A principal funo deste arquivo a conexo com o banco,
alm das funes auxiliares.
Arquivo: funcoes.py
#!/usr/bin/python
# -*- coding: utf-8 -*#Importao das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
from sqlite3 import *

#Conexo com o banco


cnx = connect('/opt/gfpopen/gfp.sqlite')
query = cnx.cursor()
#Variveis globais
CaminhoGlade = '/opt/gfpopen/glade/'
#Variveis do usurio logado
usuariologadoid = 0
usuariologadouser = ''
usuariologadonome = ''

#Mostra caixa de mensagem


def Mensagem(pai, S):
dialog = gtk.MessageDialog(pai,
gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
S)
dialog.set_title("Informao")
dialog.run()
dialog.destroy()

12 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

#Mostra mensagem de conrmao


def MsgConrmacao(pai, S):
dialog = gtk.MessageDialog(pai,
gtk.DIALOG_MODAL |
gtk.DIALOG_DESTROY_WITH_PARENT,
gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO,
S)
dialog.set_title("Conrmao")
R = dialog.run()
dialog.destroy()
if R == gtk.RESPONSE_YES:
return True
else:
return False

#Coloca edit em maisculo


def StrToMais(edt):
new_text = TiraAspa(edt.get_text().upper())
edt.set_text(new_text)

#Limpa espaos em branco


def StrToTrim(edt):
new_text = TiraAspa(edt.get_text().strip())
edt.set_text(new_text)

def TiraAspa(s):
return s.replace("'", "") Este arquivo simples e creio que com a ajuda dos
comentrios ele se auto-explica. S vou detalhar sobre a conexo com o banco, como
ela simples, comea pela importao da biblioteca pro SQLite:
from sqlite3 import *
A conexo simples. O meio de campo feito atravs de um cursor, que funciona
semelhante a uma mysql_query do PHP, por exemplo. Eu inclusive usei o nome da
varivel como query pra car mais cmodo.
#Conexo com o banco
cnx = connect('/opt/gfpopen/gfp.sqlite')
query = cnx.cursor()
Como ler os resultados retornados e como executar comandos SQL no banco, embora

13 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

j tenha aparecido no arquivo principal, vai ser mostrado logo em seguida.

Cadastro de usurios
Quando executamos o nosso programa logo na tela de login temos um boto pra
chamar a tela para cadastrar um usurio, tela esta que chamada la no gfp.py na
funo AbreCadastroUsu atravs do comando:
usuarioscadastro.UsuariosCadastro(widget, True, 0, winLogin, self)
Estamos chamando diretamente a classe e executando seu mtodo construtor. Note
que os parmetros que passamos so os mesmos que l na classe UsuariosCadastro
so declarados em:
def __init__(self, widget, novo, id, pai, paiclasse):
Agora vamos direto ao arquivo completo.
Arquivo: usuarioscadastro.py
#!/usr/bin/python
# -*- coding: utf-8 -*#Importao das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
import gobject
from sqlite3 import *
#Importa arquivos do projeto
import funcoes as f
import usuarioslista
class UsuariosCadastro(gtk.Window):
#Construtor
def __init__(self, widget, novo, id, pai, paiclasse):
#Inicializar
super(UsuariosCadastro, self).__init__()
self.AbreCadUser(widget, novo, id, pai, paiclasse)
#Cria a tela
def AbreCadUser(self, widget, novo, id, pai, paiclasse):
#Associa arquivo glade

14 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

GLADE_FILE = f.CaminhoGlade + 'usuarioslista.glade'


gui = glade.XML(GLADE_FILE, 'winUserCadastro')
#Associa controles
self.win = gui.get_widget('winUserCadastro')
self.edtSenha = gui.get_widget('edtSenha')
self.edtConrmar = gui.get_widget('edtConrmar')
self.edtNome = gui.get_widget('edtNome')
self.lblDicaUser = gui.get_widget('lblSomenteLetras')
self.edtUsuario = gui.get_widget('edtUsuario')
self.btnSair = gui.get_widget('btnCancelar')
self.imgSenha = gui.get_widget('imgAlertaSenha')
self.btnSalvar = gui.get_widget('btnOk')
self.myNovo = novo
self.MyId = id
self.MyPai = pai
self.MyPaiClasse = paiclasse
#Formata controles
self.lblDicaUser.set_markup("(somente letras, sem espaos ou acentos)")
#Associa evento dos controles
self.edtUsuario.connect("changed", lambda *a: f.StrToMais(self.edtUsuario))
self.edtUsuario.connect("focus_out_event", lambda *a: f.StrToTrim(self.edtUsuario))
self.edtNome.connect("focus_out_event", lambda *a: f.StrToTrim(self.edtNome))
self.edtSenha.connect("focus_out_event", lambda *a: self.AlertaSenha(widget))
self.edtSenha.connect("changed", lambda *a:
self.edtSenha.set_text(f.TiraAspa(self.edtSenha.get_text())))
self.edtConrmar.connect("focus_out_event", lambda *a: self.AlertaSenha(widget))
self.edtConrmar.connect("changed", lambda *a:
f.TiraAspa(self.edtConrmar.get_text()))
self.btnSair.connect('clicked', lambda *a: self.Fechar(widget))
self.btnSalvar.connect('clicked', lambda *a: self.VericaDigitacao(widget))
#Congura modo de edio do form
if self.myNovo == False:
self.edtUsuario.set_editable(False)
self.edtUsuario.set_can_focus(False)
self.lblDicaUser.set_markup("(no pode ser alterado)")
#Executa query
f.query.execute('SELECT user, nome, senha FROM usuarios WHERE id =' +
str(self.MyId))

15 de 23

#Preenche os controles
for row in f.query:

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

self.edtUsuario.set_text(row[0])
self.edtNome.set_text(row[1])
self.edtSenha.set_text(row[2])
self.edtConrmar.set_text(row[2])
self.win.set_focus(self.edtSenha)
#Abre janela
self.win.show_all()
self.imgSenha.set_visible(False)
return True

#Fechar janela
def Fechar(self, widget):
self.win.destroy() == True

#Alerta de senha
def AlertaSenha(self, widget):
if self.edtConrmar.get_text() != '':
if self.edtSenha.get_text() != self.edtConrmar.get_text():
self.imgSenha.set_visible(True)
else:
self.imgSenha.set_visible(False)

#Vericao das digitaes


def VericaDigitacao(self, widget):
#Verica usurio
if self.edtUsuario.get_text() == '':
f.Mensagem(self.win, 'Informe o usurio.')
self.win.set_focus(self.edtUsuario)
return
#Verica a senha
if self.edtSenha.get_text() == '' or self.edtSenha.get_text() !=
self.edtConrmar.get_text():
f.Mensagem(self.win, 'Verique a senha.')
self.win.set_focus(self.edtSenha)
return

16 de 23

#Verica nome
if self.edtNome.get_text() == '':
f.Mensagem(self.win, 'Informe o nome completo.')
self.win.set_focus(self.edtNome)

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

return
#Verica se o usurio j existe
if self.myNovo == True:
f.query.execute("SELECT id, user, nome FROM usuarios WHERE user = '" +
self.edtUsuario.get_text() + "'")
userExiste = False
for row in f.query:
userExiste = True
if userExiste:
f.Mensagem(self.win, 'J existe um usurio ' + self.edtUsuario.get_text() + '
cadastrado.')
self.win.set_focus(self.edtUsuario)
else:
if self.myNovo == True:
sAcao = 'cadastrado'
f.query.execute("INSERT INTO usuarios (user, nome, senha)\
VALUES('" + self.edtUsuario.get_text() + "',\
'" + self.edtNome.get_text() + "',\
'" + self.edtSenha.get_text() + "')")
else:
sAcao = 'alterado'
f.query.execute("UPDATE usuarios\
SET nome = '" + self.edtNome.get_text() + "',\
senha = '" + self.edtSenha.get_text() + "'\
WHERE id = " + str(self.MyId))
f.cnx.commit()
f.Mensagem(self.MyPai, 'Usurio ' + sAcao + ' com sucesso.')
self.MyPaiClasse.ListaUsers()
self.win.destroy() == True
Demonstrado por inteiro, atravs dos comentrios tambm vemos o que cada bloco
faz. Mas aqui quero destacar as instrues com o banco de dados. Logo aps a seo
inicial do arquivo onde montamos e chamamos a tela, por ser um cadastro vericamos
se o parmetro chamamos para insero ou edio, e se for edio selecionamos o
registro a editar e exibimos os campos nos controle. Isso ns fazemos na instruo
abaixo. Note que lemos o resultados da query num for e "pegamos" o valor dos campos
de acordo com o ndice referente posio que passamos os campos no SQL.
Esse mtodo usando loop o mesmo que usamos na listagem de todos os usurios
(conforme veremos adiante), e mesmo sendo apenas um registro (como ca bvio) no
tem problema usar o for pois ele tambm s vai executar as instrues pra atribuir os
valores aos campos uma vez, pois s um registro retornado no nosso SQL.

17 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

#Congura modo de edio do form


if self.myNovo == False:
self.edtUsuario.set_editable(False)
self.edtUsuario.set_can_focus(False)
self.lblDicaUser.set_markup("(no pode ser alterado)")
#Executa query
f.query.execute('SELECT user, nome, senha FROM usuarios WHERE id =' +
str(self.MyId))
#Preenche os controles
for row in f.query:
self.edtUsuario.set_text(row[0])
self.edtNome.set_text(row[1])
self.edtSenha.set_text(row[2])
self.edtConrmar.set_text(row[2])
E na instruo mais abaixo vamos como dar INSERT e UPDATE (o mesmo serve pro
DELETE, conforme vermos no arquivo seguinte). A diferena que estas instrues
precisam de um commit no nal, pois alteram registros no banco.
if self.myNovo == True:
sAcao = 'cadastrado'
f.query.execute("INSERT INTO usuarios (user, nome, senha)\
VALUES('" + self.edtUsuario.get_text() + "',\
'" + self.edtNome.get_text() + "',\
'" + self.edtSenha.get_text() + "')")
else:
sAcao = 'alterado'
f.query.execute("UPDATE usuarios\
SET nome = '" + self.edtNome.get_text() + "',\
senha = '" + self.edtSenha.get_text() + "'\
WHERE id = " + str(self.MyId))
f.cnx.commit()

Finalizando com a listagem


Por m vamos ver como listar os registros no banco e exib-los numa lista. No geral
no tem nada de diferente dos arquivos que j vimos, a no ser o detalhe do
componete GtkTreeView, que funciona tanto como treeview quanto como listview, que
como o usaremos. Vamos ver o arquivo inteiro, depois coment-lo.
Arquivo: usuarioslista.py

18 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

#!/usr/bin/python
# -*- coding: utf-8 -*#Importao das bibliotecas
import pygtk
pygtk.require('2.0')
import gtk
from gtk import glade
import gobject
from sqlite3 import *
#Importao de arquivos do projeto
import funcoes as f
import usuarioscadastro
class UsuariosLista(gtk.Window):
#Mtodo construtor
def __init__(self, widget):
#Inicializar
super(UsuariosLista, self).__init__()

19 de 23

#Carrega arquivo glade


GLADE_FILE = f.CaminhoGlade + 'usuarioslista.glade'
gui = glade.XML(GLADE_FILE, 'winUsuariosLista')
#Associa controles
self.win = gui.get_widget('winUsuariosLista')
self.btnSair = gui.get_widget('btnSair')
self.lstUsuarios = gui.get_widget('lstUsers')
self.btnAlterar = gui.get_widget('btnAlterar')
self.btnExcluir = gui.get_widget('btnExcluir')
#Abre Janela
self.win.show_all()
#Formata controle lista
self.modLista = gtk.TreeStore(gobject.TYPE_INT,
gobject.TYPE_STRING,
gobject.TYPE_STRING)
self.lstUsuarios.set_model(self.modLista)
self.lstUsuarios.set_headers_visible(True)
#Cria colunas da lista
self.CriarColuna('ID', 0)
self.CriarColuna('Usurio', 1)

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

self.CriarColuna('Nome completo', 2)
#Adiciona scroll TreeView
self.lstUsuarios.set_rules_hint(True)
#Carrega usurios
self.ListaUsers()
#Estado inicial
self.btnAlterar.set_sensitive(False)
self.btnExcluir.set_sensitive(False)
self.win.set_focus(self.btnSair)
#Eventos dos controles
self.btnSair.connect('clicked', lambda *a: self.Fechar())
self.btnAlterar.connect('clicked', lambda *a: self.AlterarUsuario(widget))
self.lstUsuarios.connect('cursor_changed', lambda *a: self.AtivaBotoes(True))
self.lstUsuarios.connect('row_activated', lambda *a: self.AlterarUsuario(widget))
self.btnExcluir.connect('clicked', lambda *a: self.Excluir())

#Excluir
def Excluir(self):
campo, item = self.lstUsuarios.get_selection().get_selected()
if (item != None):
myNomeExc = campo.get_value(item, 1)
if f.MsgConrmacao(self.win, "Deseja realmente excluir " + myNomeExc + "?"):
myID = campo.get_value(item, 0)
if myID != f.usuariologadoid:
f.Mensagem(self.win, "Voc s pode excluir seu prprio usurio.")
else:
f.query.execute("DELETE FROM usuarios WHERE id = " + str(myID))
f.cnx.commit()
#Lista os usuarios
self.ListaUsers()
else:
f.Mensagem(self.win, "Nenhum tem foi selecionado.")

#Ativa botoes
def AtivaBotoes(self, Ativo):
self.btnAlterar.set_sensitive(Ativo)
self.btnExcluir.set_sensitive(Ativo)

#Fecha janela
def Fechar(self):

20 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

self.win.destroy() == True

#Alterar usuario
def AlterarUsuario(self, widget):
campo, item = self.lstUsuarios.get_selection().get_selected()
if (item != None):
myID = campo.get_value(item, 0)
if myID != f.usuariologadoid:
f.Mensagem(self.win, "Voc s pode alterar seu prprio usurio.")
else:
myNome = campo.get_value(item, 1)
usuarioscadastro.UsuariosCadastro(widget, False, myID, self.win, self)
self.win.set_focus(self.lstUsuarios)
else:
f.Mensagem(self.win, "Nenhum tem foi selecionado.")

#Cria coluna da lista


def CriarColuna(self, titulo, id):
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(titulo, renderer, text = id)
column.set_resizable(False)
self.lstUsuarios.append_column(column)

#Lista usurios
def ListaUsers(self):
self.modLista.clear()
#Executa query
f.query.execute('SELECT id, user, nome FROM usuarios ORDER BY user DESC')
#Preenche a lista
for row in f.query:
myiter = self.modLista.insert_after(None, None)
self.modLista.set_value(myiter, 0, row[0])
self.modLista.set_value(myiter, 1, row[1])
self.modLista.set_value(myiter, 2, row[2])
Ento primeiro vamos comentar a criao da nossa lista. O componente foi adicionado
no arquivo ".glade" vazio, as colunas e a formatao das mesmas so criadas via
programao no bloco:

21 de 23

#Formata controle lista


self.modLista = gtk.TreeStore(gobject.TYPE_INT,
gobject.TYPE_STRING,

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

gobject.TYPE_STRING)
self.lstUsuarios.set_model(self.modLista)
self.lstUsuarios.set_headers_visible(True)
#Cria colunas da lista
self.CriarColuna('ID', 0)
self.CriarColuna('Usurio', 1)
self.CriarColuna('Nome completo', 2)
#Mostra barras de rolagem na lista
self.lstUsuarios.set_rules_hint(True)
Note que temos a uma funo CriarColuna, que foi criado pra no repetirmos cdigo,
j que a criao de cada coluna usa os mesmos comandos praticamente. Esta funo
declarada mais abaixo no arquivo:
#Cria coluna da lista
def CriarColuna(self, titulo, id):
renderer = gtk.CellRendererText()
column = gtk.TreeViewColumn(titulo, renderer, text = id)
column.set_resizable(False)
self.lstUsuarios.append_column(column)
Por m temos a funo ListaUsers, onde fazemos um loop com os resultados da query
no banco e inserimos linha por linha:
#Lista usurios
def ListaUsers(self):
self.modLista.clear()
#Executa query
f.query.execute('SELECT id, user, nome FROM usuarios ORDER BY user DESC')
#Preenche a lista
for row in f.query:
myiter = self.modLista.insert_after(None, None)
self.modLista.set_value(myiter, 0, row[0])
self.modLista.set_value(myiter, 1, row[1])
self.modLista.set_value(myiter, 2, row[2])
E basicamente isso, procurei detalhar o bsico de forma objetiva. Talvez tenha
deixado alguma dvida pois o assunto realmente longo para esmiuar, por isso
procurei expor um cdigo o mais auto-explicvel possvel, e me coloco disposio pra
pra ajudar no que for preciso pra entender melhor. E nalmente, vai um print do
aplicativo:

22 de 23

21-06-2013 23:23

Desenvolvendo aplicaes GUI simples em Python & Gla...

http://www.vivaolinux.com.br/artigos/impressora.php?co...

Post original no meu blog: Desenvolvendo aplicaes GUI simples em Python & Glade
(PyGTK) com banco de dados SQLite - pedro-araujo.com

http://www.vivaolinux.com.br/artigo/Desenvolvendo-aplicacoes-GUI-simplesem-Python-e-Glade-(PyGTK)-com-banco-de-dados-SQLite
Voltar para o site

23 de 23

21-06-2013 23:23

Potrebbero piacerti anche