Desenvolvendo aplicações GUI simples em Python & Glade (PyGTK) com banco de dados SQLite

O objetivo deste artigo é mostrar de forma objetiva como realizar procedimentos básicos de programação, então vamos abordar a criação da parte gráfica do programa, vamos falar de como usar controles e eventos simples na nossa aplicação, como botões, caixas de textos, janelas, diálogos, listas, o básico necessário da linguagem Python e como fazer as principais operações com banco de dados.

[ Hits: 169.410 ]

Por: Perfil removido em 28/07/2010


Agora vamos programar



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.

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Por que Python?
   3. Preparando o ambiente
   4. Dando forma à aplicação
   5. Agora vamos programar
   6. Continuando a programar
   7. Finalizando com a listagem
Outros artigos deste autor

AFT : Tecnologia para Formatação Avançada - Conceitos básicos

Tunando sistemas de arquivos para GNU/Linux

A internet é inocente

expr - Definição e uso do comando

Usando aMSN com plugin Music com suporte ao Juk e Amarok

Leitura recomendada

ISO8583py - Utilizando Python para o tratamento de mensagens ISO8583

Construindo um portscanner TCP com Python

Alimentando Desktopcouch com Zeitgeist

Python - Uma linguagem orientada a objetos

Esteganografia e Esteganálise: transmissão e detecção de informações ocultas em imagens digitais

  
Comentários
[1] Comentário enviado por fonini em 29/07/2010 - 08:27h

Parabéns pelo excelente artigo!

[2] Comentário enviado por balani em 29/07/2010 - 09:40h

Excelente artigo, estou iniciando em Python, seu artigo me ajudará muito, nesse aprendizado.

Parabens!

Abraços


Adriano R. Balani

[3] Comentário enviado por gtuxed em 29/07/2010 - 12:34h

Bom artigo, parabéns.

Estes dias fiz meu primeiro aplicativo com PyGTK e apesar de também ser iniciante em python, não achei muito difícil exceto por ainda achar as estruturas liststore/treestore um pouco "overkill" rsrs.

Falando mais sobre estas estruturas, acho que apesar da flexibilidade que elas oferecem, deveria haver uma interface mais simples para coisas mais pragmáticas.

Mas isso é mais um problema com GTK do que com PyGTK (que é apenas um binding).

hehe, olha só como é complexo criar uma simples lista e apresentar...

##

# Criamos um modelo ListStore(<tipo>,<tipo>,...)
liststore = gtk.ListStore(str)

# Baseado no modelo criamos uma treeview
treeview = gtk.TreeView(liststore)

# Precisamos criar um "renderizador" (será que estou usando blender, engine 3d, etc.? rsrs)
textrenderer = gtk.CellRendererText()

# Adicionamos a coluna ao treeview
column = gtk.TreeViewColumn('Nome da coluna', textrenderer, text=0)
treeview.append_column(column)

# Adicionamos valores à lista
for row in ['a','b','c']:
itt = liststore.append([row])

##

Poderia ser assim:

##

# Criamos a lista
list = gtk.List(str)

# Adicionamos valores à ela
list.append('teste')

##

Da pra fazer isso facilmente, mas acho que isso já deveria existir rsrs

[4] Comentário enviado por gomes-fdr em 29/07/2010 - 16:26h

Muito bom o seu artigo, parabens.

Para mim servirá como material de apoio para o inicio de aplicativos baseados em Python(desktop).

Saudações.

[5] Comentário enviado por albfneto em 01/08/2010 - 18:48h

émuitobom esse artigo.! 10

[6] Comentário enviado por Lisandro em 21/12/2010 - 09:05h

Parabéns pelo artigo. Muito Bom.

[7] Comentário enviado por quemsoueu em 06/07/2012 - 08:18h

Cara seu artigo abriu meus olhos eu tava quase desistindo de desenvolver o software.
A dúvida é com o tkinter eu consigo rodar ele no windows como java, entretanto como faço para rodar ele no windows ele foi escrito com o pygtk e glade, e preciso rodar numa estação Win, acaso você já fez isso?

[8] Comentário enviado por leo523 em 10/06/2013 - 10:17h

Ótimo post, mas atualmente o modo é um pouco diferente, ao inves de usar a biblioteca glade.XML para chamar o xml, usa-se o gtk.builder.

Respondendo o comentário acima, para distribuir no Windows vc deve instalar o pygtk completo que esta neste link :
http://ftp.gnome.org/pub/GNOME/binaries/win32/pygtk/2.24/

[9] Comentário enviado por wladimir58 em 15/06/2016 - 16:27h

Nunca consegui usar as interfaces do Glade nos meus programas em Python




Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts