2 | ||
Editor: geon
Time: 2011/10/13 21:13:38 GMT+2 |
||
Note: pridavani znacek 2x-3x |
changed: - .. image:: py25.png :align: right 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)
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.
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()
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()