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.