PyGObject e GTK3

No último post eu mostrei como criar interfaces gráficas usando PyGtk e o Glade para moldar a interface, porém o projeto PyGTK já não é mais desenvolvido sendo recomendado a utilização do PyGObject que é um módulo para python que nos permite usar os recursos disponíveis através do GObject que atualmente é a base do GTK3/Gnome3.

Como recentemente eu migrei para o Gnome 3 decidi testar o PyGObject portando a aplicação que desenvolvi no último post , o que foi bem simples de se fazer.


 A partir da versão 3.10 do Glade é possível criar interfaces em GTK3, então se você decidir utilizar essa versão do GTK certifique-se de que o Glade está nessa versão ou superior.

Para ficar mais interessante eu portei o código para python 3 =D


Não existe muita diferença no desenvolvimento com PyGTK ou PyGObject, na verdade as funções são praticamente as mesmas, havendo algumas diferenças nos nomes de algumas funções.

Na criação da interface através do Glade a única diferença é o Sinal do gtk.Window(), na versão 2.* do GTK utilizamos o sinal destroy para fechar a janela, agora na versão 3 do GTK usamos o sinal  delete-event


Com relação a criação da interface através do Glade, essa é basicamente a única diferença, obviamente a maior diferença será no código python, mas nem tanto quanto você deve estar pensando.

Antes de começar a falar sobre o código em si, verifique os pacotes instalados em seu sistema pois apesar do pygobject vir instalado como padrão na maioria das distros atuais, ele não vem instalado para a versão 3 do python sendo necessário instalar o mesmo.
No fedora 16 você pode instalar diretamente através do repositório oficial, o pacote se chama python3-gobject, caso utilize outra distro verifique se algum pacote possuí um nome semelhante.

UPDATE [20/01/2012] : no ubuntu o pacote para python3 se chama python3-gi


Utilizando o PyGTK nós iniciamos nosso programa obviamente importando o módulo: 

 
import pygtk
pygtk.require("2.0")
import gtk 

Agora com PyGObject nós importamos o módulo Gtk da seguinte forma:

from gi.repository import Gtk

Preste atenção nesse ponto, pois perceba que não importamos mais o Gtk com a letra "G" minúscula e sim com ela maiúscula, sendo assim caso esteja portando algum programa preste atenção pois as funções não são mais chamadas assim por exemplo: gtk.Builder , mas sim por Gtk.Builder

Essa basicamente seria a maior mudança entre o PyGTK e o PyGObject, mas quando eu fui utilizar a classe Gtk.Clipboard eu percebi que houve mudanças em sua utilização, mudanças que na verdade ainda estão ocorrendo.

Para utilizarmos o clipboard, também será necessário importar o módulo Gdk e utilizar a classe Gdk.atom, então para instanciarmos a classe Gtk.Clipboard e podermos utiliza-la faremos da seguinte forma:


from gi.repository import Gtk, Gdk

atom = Gdk.atom_intern("CLIPBOARD", True)
clipboard = Gtk.Clipboard.get(atom)
#obtendo o texto armazenado atualmente no clipboard
text = clipboard.wait_for_text()
#copiando um novo text opara o clipboard
clipboard.set_text("Texto", -1) 


Se você visualizar o código que criei no último post poderá perceber a diferença na utilização do clipboard, basicamente a mudança entre gtk.Clipboard_get para Gtk.Clipboard.get e a necessidade de passar o comprimento na função .set_text("Texto", -1) nesse último caso eu pesquisei na web e pelo que encontrei os desenvolvedores já estão trabalhando para remover essa obrigatoriedade de passar o comprimento como argumento para a função.

Finalizando essas são as únicas diferenças que eu encontrei utilizando o PyGObject, obviamente deve haver mais algumas mudanças com nomes de classes e funções, porém se você já utilizou PyGTK e está habituado a utiliza-lo não enfrentará grandes problemas em migrar para o PyGObject. 


Abaixo segue o código do programa em PyGTK (do último post) e o código portado para PyGObject e Python 3.

PyGTK

#!/usr/bin/env python
#-*- coding: utf-8 -*-

import pygtk
pygtk.require("2.0")
import gtk
    
  
class InverterApp(object):
    def __init__(self):
        builder = gtk.Builder()
        builder.add_from_file("inverter.glade")
        builder.connect_signals({
                                "on_window1_destroy": gtk.main_quit,
                                "on_button_invert_clicked": self.invert_url,
                                "on_entry_text_activate": self.invert_url,
                                "on_copy_activate": self.copy_text,
                                "on_paste_activate": self.paste_text,
                                "on_delete_activate": self.delete_text,
                                "on_about_activate": self.about_window
                                })
        self.window = builder.get_object("window1")
        self.window.show()
        self.text_area = builder.get_object("entry_text")
        self.about = builder.get_object("aboutdialog")
        
    def about_window(self, widget):
        self.about.run()
        self.about.hide()
        
    def invert_url(self, widget):
        text = self.text_area.get_text()
        text = text[::-1]
        self.text_area.set_text(text)
        
    def copy_text(self, widget):
        clipboard = gtk.clipboard_get()
        text = self.text_area.get_text()
        clipboard.set_text(text)
        clipboard.store()
        
    def paste_text(self, widget):
        clipboard = gtk.clipboard_get()
        text = clipboard.wait_for_text()
        self.text_area.set_text(text)
        
    def delete_text(self, widget):
        self.text_area.set_text("")
              
        
if __name__ == "__main__":
    app = InverterApp()
    gtk.main()



 PyGObject

 
#!/usr/bin/python3

from gi.repository import Gtk, Gdk

class Inverter(object):
    def __init__(self):
        builder = Gtk.Builder()
        builder.add_from_file("inverter.glade")
        self.window = builder.get_object("window")
        self.window.show()
        self.url = builder.get_object("entry")
        self.about = builder.get_object("aboutdialog")
        builder.connect_signals({
                                "gtk_main_quit": Gtk.main_quit,
                                "on_entry_activate": self.invert_url,
                                "on_button_clicked": self.invert_url,
                                "on_copy_activate": self.copy_text,
                                "on_paste_activate": self.paste_text,
                                "on_delete_activate": self.delete_text,
                                "on_about_activate": self.about_window,
                                })
                                
    def invert_url(self, widget):
        text = self.url.get_text()
        text = text[::-1]
        self.url.set_text(text)
        
    def copy_text(self, widget):
        atom = Gdk.atom_intern("CLIPBOARD", True)
        clipboard = Gtk.Clipboard.get(atom)
        text = self.url.get_text()
        clipboard.set_text(text, -1)
        clipboard.store()
        
    def paste_text(self, widget):
        atom = Gdk.atom_intern("CLIPBOARD", True)
        clipboard = Gtk.Clipboard.get(atom)
        text = clipboard.wait_for_text()
        self.url.set_text(text)
        
    def delete_text(self, widget):
        self.url.set_text("")
        
    def about_window(self, widget):
        self.about.run()
        self.about.hide()
        
if __name__ == "__main__":
    app = Inverter()
    Gtk.main()


Praticamente o mesmo código e com algumas pequenas alterações a aplicação foi portada para GTK3








Baixe o arquivo Glade e .py aqui

4 Comentário(s) em “PyGObject e GTK3”

  1. Olá Rafael,

    Gostei muito deste tutorial e da versão anterior e pensei num problema
    (que poderia ser bom para um próximo tutorial ou pra deixar este ainda melhor :D )

    se o teu programa tivesse por exemplo "ratio buttons", com 3 opções:

    1-inverse URL(função default)
    2-Capitalise URL
    3-Anagramatizar(Fazer um anagrama da URL)

    das quais o usuário pudesse escolher uma delas e em seguida clicar no botão ou apertar enter para que o programa faça sua parte.


    Neste caso como ficaria a parte dos signals?


    abração

    [Responder comentário]
  2. Olá Cassimiro,

    Primeiramente muito obrigado.
    Fiz um com as suas sugestões e explico como será realizado os signals, você pode verifica-lo neste link:

    http://www.sourcecode.net.br/2013/06/radio-buttons-com-glade-e-pygobject.html

    Espero que isso te ajude, qualquer dúvida basta perguntar =)!

    Abraço

    [Responder comentário]
  3. Muito Obrigado por partilhar do seu conhecimento! Esse tutorial me foi de exorbitante ajuda, pois estou estudando python por conta própria, e quando chega o momento de criar a interface gráfica a coisa se complica; As informações na internet estão muito escassas e defasadas.
    Parabéns pela dedicação, e pela qualidade dos Tutoriais, muito bem ilustrados, bem explicados...
    Abraço!

    [Responder comentário]

Deixe um comentário