Python a Glade
Jak určitě víte, existuje skvělý nástroj na naklikání GTK+ widgetů - glade http://glade.gnome.org/ (případně glade pro windows http://gladewin32.sourceforge.net/modules/news/). Z něj vyleze XML soubor, který se da použít z mnoha programovacích jazyků a jedním z nich je i Python. Budu sem dávat svoje postřehy, současně s tím, jak se GTK+ učím.
První - změna labelu po kliknutí na tlačítko
Cíl: po kliknutí na tlačítko button1 se změní text labelu label1 na současný text v entry1.
Widgety: window, fixed, label, entry, button (learn1.glade soubor http://www.py.cz/learn1.glade)
Zdrojový kód:
# -*- coding: cp1250 -*-
#!/usr/bin/python
import os,sys
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
def glade_file_missing(fname):
"Rucne delane okno, ktere se objevi, kdyz se zapomeme stahnout *.glade soubor"
url="http://www.py.cz/"
win=gtk.Window(gtk.WINDOW_TOPLEVEL)
win.connect("destroy", gtk.main_quit)
win.set_resizable(False)
win.set_border_width(10)
win.set_position(gtk.WIN_POS_CENTER)
win.set_title(u"Upozornění na chybějící soubor")
vbox=gtk.VBox(False, 3)
win.add(vbox)
vbox.show()
hbox=gtk.HBox(False,3)
vbox.pack_start(hbox)
image=gtk.Image()
image.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
button=gtk.Button(None,gtk.STOCK_STOP)
button.connect("clicked",gtk.main_quit)
label=gtk.Label(u"CHYBÍ SOUBOR "+fname+"\n\n"+url+fname)
hbox.pack_start(image)
hbox.pack_start(label)
vbox.pack_start(button)
win.show_all()
gtk.main()
sys.exit(1)
class window1Handlers: #vytvorim si tridu jejiz metody budou obsluhovat udalosti widgetu
"""metody jsou obsluha udalosti widgetu, jmeno metody se musi shodovat se jmenem udalosti nastavenym v Glade"""
def on_window1_destroy(widget):
gtk.main_quit()
def on_button1_clicked(widget):
window1['label1'].set_text(window1['entry1'].get_text())
class WidgetsWrapper:
"Zde se zajistí nactení *.glade souboru a svázaní jeho definovaných událostí s funkcemi zde."
def __init__(self,file_name,widget_name,handlers_class):
self.glade_file=file_name
self.widgets = gtk.glade.XML (file_name, widget_name)
self.widgets.signal_autoconnect(handlers_class.__dict__)
def __getitem__(self, key):
"""diky tehle fci jde pouzit jmeno_instance['jmeno_widgetu']"""
return self.widgets.get_widget(key)
# ---- zacatek -----------------
if not os.path.exists("learn1.glade"):
glade_file_missing("learn1.glade")
window1=WidgetsWrapper("learn1.glade", "window1",window1Handlers)
gtk.main()
Druhý - minitextový editor s dialogy pro otevření a uložení souboru
Cíl: obsluha gtk.filechooserdialog-u jako dialogu pro otevření a uložení souboru
Widgety: window, vbox, hbox, alignment, label, button, textview, filechooserdialog, dialog, image ("learn2.glade soubor":http://www.py.cz/learn2.glade)
V tomto příkladu lze otevřít pouze soubory uložené v ISO nebo UTF kódování - pro zobrazení obsahu souboru ve win-1250 je potreba odkomentovat radek kodu s konverzi na unicode (data=unicode(data,"cp1250"))
Zdrojový kód:
#!/usr/bin/python
import sys,os
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
def glade_file_missing(fname):
url="http://www.py.cz/"
win=gtk.Window(gtk.WINDOW_TOPLEVEL)
win.connect("destroy", gtk.main_quit)
win.set_resizable(False)
win.set_border_width(10)
win.set_position(gtk.WIN_POS_CENTER)
win.set_title("Chybi soubor")
vbox=gtk.VBox(False, 3)
win.add(vbox)
vbox.show()
hbox=gtk.HBox(False,3)
vbox.pack_start(hbox)
image=gtk.Image()
image.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_DIALOG)
button=gtk.Button(None,gtk.STOCK_STOP)
button.connect("clicked",gtk.main_quit)
label=gtk.Label("CHYBI SOUBOR "+fname+"\n\n"+url+fname)
hbox.pack_start(image)
hbox.pack_start(label)
vbox.pack_start(button)
win.show_all()
gtk.main()
sys.exit(1)
if not os.path.exists("learn2.glade"):
glade_file_missing("learn2.glade")
class window1Handlers:
"""
metody jsou obsluha udalosti widgetu, jmeno metody se musi shodovat se jmenem udalosti nastavenym v Glade
window1 - globalni promenna - instance tridy WidgetsWrapper
"""
def on_window1_destroy(widget):
gtk.main_quit()
def on_button1_clicked(widget):
"""otevre dialog pro otevreni souboru a obsah souboru vypise do textview"""
open_dialog=gtk.glade.XML(window1.glade_file,"open_dialog").get_widget("open_dialog") #nactu si dialog pro otevreni souboru
retval=open_dialog.run()
if retval==gtk.RESPONSE_OK:
fname=unicode(open_dialog.get_filename())
fin=open(fname,"r")
data=fin.read()
#data=unicode(data,"cp1250") #odkomentujte tento radek, pokud chcete nacitat soubory v kodovani windows-1250
fin.close()
window1["label2"].set_text(fname) # zobrazeni soucasneho jmena souboru
textview=window1["textview1"] # textview je widget, ktery zobrazuje obsah gtk.TextBuffer
text_buffer=gtk.TextBuffer(None) # vytvorim buffer
textview.set_buffer(text_buffer) # reknu textview ktery buffer ma zobrazovat
text_buffer.set_text(data) # a zapisu data do bufferu
# po zavolani run() je treba manualne dialog znicit - pokud tuhle metodu nezavolate, dilalog se neukonci, ale uz nebude "aktivni"
open_dialog.destroy()
def on_button2_clicked(widget):
"""ulozi obsah textview do souboru, ktery je vybran pomoci save dialogu"""
save_dialog=gtk.glade.XML(window1.glade_file,"save_dialog").get_widget("save_dialog")
save_dialog.set_filename(window1["label2"].get_text())
retval=save_dialog.run()
if retval==gtk.RESPONSE_OK:
fname=unicode(save_dialog.get_filename())
if os.path.exists(fname): # okud uz soubor existuje, zeptam se, jestli prepsat
overwrite_dialog=gtk.glade.XML(window1.glade_file,"dialog_overwrite").get_widget("dialog_overwrite")
retval=overwrite_dialog.run()
if retval!=gtk.RESPONSE_OK: # pokud nebylo stisknuto tlacitko potvrzujici prepsani
overwrite_dialog.destroy()
save_dialog.destroy() #ukoncim oba dialogy
return() # a vyskocim z cele metody
overwrite_dialog.destroy()
text_buffer=window1['textview1'].get_buffer() # protoze nelze pracovat primo s textview, vytahnu si buffer ktery zobrazuje
start=text_buffer.get_start_iter() # ke cteni z bufferu je potreba znat zacatek a konec useku, ktery chceme cist - tady mam zacatek
end=text_buffer.get_end_iter() # a tady konec
data=text_buffer.get_text(start, end, True) # prectu data z bufferu - od pozice start do pozice end, vcetne "hidden" znaku
open(fname, 'w').write(data) # a zapisu je do souboru
window1['label2'].set_text(fname) # nastavim label se jmenem souboru, na soubor do jakeho jsem to ulozil
save_dialog.destroy()
class WidgetsWrapper:
def __init__(self,file_name,widget_name,handlers_class):
self.glade_file=file_name
self.widgets = gtk.glade.XML (file_name, widget_name)
self.widgets.signal_autoconnect(handlers_class.__dict__)
def __getitem__(self, key):
"""diky tehle fci jde pouzit jmeno_instance['jmeno_widgetu']"""
return self.widgets.get_widget(key)
window1=WidgetsWrapper("learn2.glade", "window1",window1Handlers)
gtk.main()
Zdroje
- Vytvoření jednoduchého dialogu: http://www.writelinux.com/glade/ (anglicky)
- Úvod do práce s Glade 2: http://www.kplug.org/glade_tutorial/glade2_tutorial/glade2_introduction.html (anglicky)