Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
1 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
21-06-2013 23:23
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.
21-06-2013 23:23
3 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
4 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
5 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
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.
7 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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.')
21-06-2013 23:23
9 de 23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
21-06-2013 23:23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
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
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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 *
12 de 23
21-06-2013 23:23
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
http://www.vivaolinux.com.br/artigos/impressora.php?co...
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
http://www.vivaolinux.com.br/artigos/impressora.php?co...
15 de 23
#Preenche os controles
for row in f.query:
21-06-2013 23:23
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)
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
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
http://www.vivaolinux.com.br/artigos/impressora.php?co...
18 de 23
21-06-2013 23:23
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
21-06-2013 23:23
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
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.")
#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
21-06-2013 23:23
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
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