Ještě než se vrhneme na kalkulačku a onen prohlížeč, je nutné si představit gtk.Entry(). gtk.Label(), gtk.TextView() a gtk.ScrolledWindow(), aneb teorii neutečete.
Popis jednotlivých widgetů není úplný, a to ani zdaleka. Jednotlivé widgety jsou plně popsány v referenční příručce.
gtk.Label()
Klasický nápis. Zatímco v Qt tento widget dokáže fungovat i jako zobrazovač obrázků a další možnosti, v GTK slouží jen a pouze svému účelu.
Přesto je dost věcí, co s ním lze dělat (natáčet, ohýbat…). Nás bude nejvíce zajímat zadání a přečtení textu.
vytvoření
nas_napis = gtk.Label(labemax=0)
max – Maximální počet znaků. Výchozí je 0 – maximum. Jinak vkládat hodnotu mezi 0 a 65 536.
metody
set_label(str) – Nastavit text. Parametr je klasický řetězec.
get_label() – Získat text. Text je získán ve formátu klasický řetězec.
gtk.Entry()
Je to klasický widget pro získávání jednoduchých a jednořádkových údajů od uživatele. Jiná prostředí tomu říkají LineEdit, neboli editační linka.
Zde se zaměříme jen na základ, a to je vytvoření, přečtení obsahu a zápis obsahu.
vytvoření
nas_entry = gtk.Entry(max=0)
max – Maximální počet znaků. Výchozí je 0 – maximum. Jinak vkládat hodnotu mezi 0 a 65 536.
metody
set_text(text) – Nastavit text. Parametr je klasický řetězec.
get_text() – Získat text. Text je získán ve formátu klasický řetězec.
insert_text(text, position=0) – Vložit text. text je řetězec a position je index.
signály
„activate“ – editační linka byla aktivována (většinou stiskem Enteru)
gtk.TextView()
Další klasický widget. Tentokráte nejen řádka, ale celé textové pole, někde označované jako TextBox. To nám slouží k dvěma účelům. První a častější je zobrazení textu. Druhý, méně častý, je pak jeho editace. Získávání textu je ovšem složitější, proto jej zatím vynechám a v následujícím příkladu se omezím jen na zadávání.
Samotný TextView() je „rozdělen“ na dvě části. TextBuffer(), kde máme samotný text a TextView(), který nám slouží k jeho zobrazení. Od toho se odvíjí i jejich metody.
vytvoření
textovy_editor = gtk.TextView(buffer=None)
buffer – Onen textový buffer. Pokud jej nepřiřadíme při vytvoření, je nutno jej přiřadit později pomocí set_buffer()
.
gtk.TextBuffer()
vytvoření
textovy_buffer = gtk.TextBuffer(table=None)
table – Tabulka tagů pro formátování textu. Toto nás zatím zajímat nebude.
metody
set_text(text) – Nastavit text. Parametr je klasický řetězec.
Těch metod je u obou text objektů velké množství. To abyste se mohli dokonale v textovém editoru vyřádit. Pokud ale už teď myslíte na napsání vlastního editoru zdrojového kódu (třebas ten Python), tak zadržte. Onu práci správně nastavit textview a nějaké „fičurky“ navíc za vás už někdo udělal. Vznikl gtk.SourceView() a jak odkaz dokazuje, v PyGTK na něj máme binding a jistojistě se na něj později podíváme.
gtk.ScrolledWindow()
Jak na to si řekneme v jiném díle. Samotné GTK se dost drží unixové filosofie, každý -něco- bude dělat jen svou práci a bude ji dělat dobře. Toto je tedy widget, který umí „scrollovat“ prvky v sobě vložené. On totiž samotný TextView se roztáhne na velikost textu a to, že je to už hrubě mimo prostor obrazovky, ho nikterak nezajímá. Proto jej musíme vložit do toho widgetu, který přidává posuvníky a podle jejich pozice ukazuje část vloženého widgetu.
vytvoření
posuvnikove_okno = gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
hadjustment, vadjustment – Chování samotného posuvníkového okna (min. velikost, max.velikost, krok), zatím necháme výchozí.
metody
add_with_viewport(child) – vložit widget-child do ScrollWindow set_policy(hscrollbar_policy, vscrollbar_policy) – Kdy se mají posuvníky objevit. Možnosti jsou:
- gtk.POLICY_ALWAYS – vždy
- gtk.POLICY_AUTOMATIC – když je to třeba
- gtk.POLICY_NEVER – nikdy
kalkulacka.py
#!/usr/bin/env python #-*- coding: UTF-8 -*- from __future__ import division import sys try: import pygtk pygtk.require("2.0") import gtk except: print "Error: PyGTK and GTK 2.xx must be installed to run this application. Exiting" sys.exit(1) class kalkulacka(gtk.Window): def __init__(self): gtk.Window.__init__(self) # Pomocná proměnná self.zadano = False # Hlavní prvky, linka a klávesnice self.zadavani = gtk.Entry() self.nakresli_klavesnici() # VBox self.vbox = gtk.VBox(False, 10) self.vbox.pack_start(self.zadavani, False) self.vbox.pack_end(self.tabulka) # Okno self.add(self.vbox) self.set_border_width(10) self.set_title("Kalkulačka") self.set_default_size(200, 200) self.connect("destroy", gtk.main_quit) self.show_all() def nakresli_klavesnici(self): " Vytvoření tabulky a její naplnění tlačítky" self.tabulka = gtk.Table(4, 4, True) self.tabulka.set_col_spacings(5) self.tabulka.set_row_spacings(5) self.klavesnice = [] # Vytvoření a napojení tlačítek 0 - 9 for i in xrange(10): self.klavesnice.append(gtk.Button(str(i))) self.klavesnice[i].connect("clicked", self.vloz_znak, str(i)) # Vložení devíti kláves do tabulky for radek in xrange(3): for sloupec in xrange(3): klavesa = 3*radek+sloupec+1 self.tabulka.attach(self.klavesnice[klavesa], sloupec, sloupec+1, 2-radek, 2-radek+1) self.tabulka.attach(self.klavesnice[0], 0, 1, 3, 4) # Vložení klávesy 0 # Početní klávesy pocetni_klavesy = ["+", "-", "*", "/"] for radek in xrange(len(pocetni_klavesy)): klavesa = pocetni_klavesy[radek] self.klavesnice.append(gtk.Button(klavesa)) self.tabulka.attach(self.klavesnice[10+radek], 3, 4, radek, radek+1) self.klavesnice[10+radek].connect("clicked", self.ukon, klavesa) # Nakonec klávesa = přes dvě políčka self.klavesnice.append(gtk.Button("=")) self.klavesnice[14].connect("clicked", self.vysledek) self.tabulka.attach(self.klavesnice[14], 1, 3, 3, 4) def vloz_znak(self, widget, znak): " Obsluha vložení znaku - vykreslení jej na lince " # Pokud je toto druhé číslo/vstup, vymažeme předchozí if self.zadano: self.zadavani.set_text("") self.zadano = False # Text rozšíříme o náš znak (-1 je poslední pozice) self.zadavani.insert_text(znak, -1) def ukon(self, widget, ukon=None): " Přečtení úkonu a uložení prvního číslo k počítání " self.ukon = ukon self.x = self.zadavani.get_text() self.zadano = True def vysledek(self, widget): " Zobrazení výsledku " self.y = self.zadavani.get_text() self.vysledek = eval(self.x + self.ukon + self.y) self.zadavani.set_text(str(self.vysledek)) self.zadano = True if __name__ == "__main__": aplikace = kalkulacka() gtk.main()
Rozbor
#-- coding: UTF-8 --
Informování Pythonu, že celý kód je v Unicode formátu a jako takový jej má i zpracovat, tudíž mohu dle libosti využívat české znaky jak v komentářích, tak řetězcích… i v proměnných, ale to se nedělá.
from __future__ import division
Vypůjčení si dělení z nadcházející verze Pythonu, která výsledek nevrací celočíselně, ale v desetinných místech.
def __init__(self)
Zde není co říci. Snad jen poznámka, že samotné kreslení klávesnice jsem dal do samostatné funkce, aby mi to __init__() příliž neznepřehlednilo.
# Vytvoření a napojení tlačítek 0 – 9
Zde předvádím, že prvky nemusí být jen samostatné proměnné, ale mohou být klidně i, v souladu s filosofií Pythonu, prvky v seznamu. Ten seznam generuji, abych nemusel psát hodně zbytečně se opakujícího se kódu.
Dále abych nemusel v callbacku zjišťovat, jaké že to tlačítko bylo stisknuto (hromada ifů), stejnak mě to zajímá jen kvůli vložení znaku do linky, předávám onen znak rovnou jako parametr ( str(i)
)
# Vložení devíti kláves do tabulky
Opět se snažím si ulehčit práci. Takže i onu základní matici 3×3 tlačítek generuji.
Nejdřív musím zjistit, s jakou klávesou budu pracovat. To je 3*řádek (rozdělení kláves do trojic) + sloupec (jednotlivá klávesa z oné trojce) + 1 (nechci začínat od nuly, ale od jedničky).
Tlačítka pak umisťuji do tabulky. To sice fungovalo, ale řazena byla odshora dolů, což je pravý opak numerické klávesnice. Proto řádek v tabulce „invertuji“ 2-radek ⇒ místo 0,1,2 získám 2, 1, 0. Počítám si jen levou čáru políčka. Pravá je to samé + 1.
# Početní klávesy
Samotné klávesy jsem si hodil do seznamu, který pak probírám.
self.zadano
Pomocná proměnná, kterou si zjišťuji, zda při vkládání znaku do linky mám přidávat k existujícímu textu nebo ten text vymazat a začít od začátku.
prohlizec.py
#!/usr/bin/env python #-*- coding: UTF-8 -*- import sys try: import pygtk pygtk.require("2.0") import gtk except: print "Error: PyGTK and GTK 2.xx must be installed to run this application. Exiting" sys.exit(1) class jednoduchy_textovy_prohlizec: def __init__(self): self.okno = gtk.Window() self.okno.set_title("Textový editor") self.okno.set_border_width(10) # Menu self.adresa = gtk.Entry() self.napis_adresa = gtk.Label("Adresa:") self.tlacitko_otevrit = gtk.Button("Otevřít") # Editor self.textovy_buffer = gtk.TextBuffer() self.textovy_prohlizec = gtk.TextView(self.textovy_buffer) self.posuvnikove_okno = gtk.ScrolledWindow() self.posuvnikove_okno.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.posuvnikove_okno.add_with_viewport(self.textovy_prohlizec) # Zabalení menu do HBoxu self.hbox_menu = gtk.HBox(False, 5) self.hbox_menu.pack_start(self.napis_adresa, False) self.hbox_menu.pack_start(self.adresa) self.hbox_menu.pack_start(self.tlacitko_otevrit, False) # Zabalení menu a editoru do VBoxu self.vbox = gtk.VBox(False, 5) self.vbox.pack_start(self.hbox_menu, False) self.vbox.pack_end(self.posuvnikove_okno) self.okno.add(self.vbox) self.okno.show_all() self.okno.connect("destroy", gtk.main_quit) self.adresa.connect("activate", self.precti_soubor) self.tlacitko_otevrit.connect("clicked", self.precti_soubor) def precti_soubor(self, widget): try: cesta_k_souboru = self.adresa.get_text() nazev_souboru = cesta_k_souboru.split("/")[-1] soubor = file(cesta_k_souboru, "r") self.textovy_buffer.set_text(soubor.read()) soubor.close() self.okno.set_title(nazev_souboru) except: self.adresa.set_text("") self.okno.set_title("Textový editor") self.textovy_buffer.set_text("") if __name__ == "__main__": aplikace = jednoduchy_textovy_prohlizec() gtk.main()
Rozbor
Zde snad ani není co rozebírat. Vše již bylo řečeno.
Příště
Budeme zkoumat samotné PyGTK a jeho referenční příručku.