V této lekci napíšeme velmi jednoduchou aplikaci GTK, která načítá a zobrazuje soubory s obrázky. Naučíte se tyto věci:
Psát základní uživatelské rozhraní GTK v jazyce Python
Zacházet s událostmi pomocí připojení signálu na obsluhu signálu.
Rozvrhnout uživatelské rozhraní GTK pomocí kontejnerů.
Načíst a zobrazit soubor s obrázkem.
Abyste mohli pokračovat v této lekci, budete potřebovat následující:
Nainstalovanou kopii IDE Anjuta
Základní znalosti programovacího jazyka Python
Než začnete s kódováním, musíte ve studiu Anjuta vytvořit nový projekt. Tím se vytvoří všechny soubory, které budete později potřebovat k sestavení a spuštění kódu. Je to také užitečné kvůli udržení všeho pohromadě.
Spusťte IDE Anjuta a klikněte na
Na kartě
Ujistěte se, že
Klikněte na
Pojďme se podívat, jak by úplně základní aplikace Gtk mohl vypadat v jazyce Python:
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys
class GUI:
def __init__(self):
window = Gtk.Window()
window.set_title ("Hello World")
window.connect_after('destroy', self.destroy)
window.show_all()
def destroy(window, self):
Gtk.main_quit()
def main():
app = GUI()
Gtk.main()
if __name__ == "__main__":
sys.exit(main())
Podívejme se, co se stane:
První řádek importuje jmenný prostor Gtk (tzn. vloží knihovnu Gtk). Knihovny jsou poskytovány pomocí GObject Introspection (gi), který poskytuje vazbu jazyka pro řadu knihoven GNOME.
Metoda __init__
třídy GUI
vytvoří (prázdné) okno Gtk.Window
, nastaví jeho název do záhlaví a napojí signál, aby se aplikace ukončila při zavření okna. Toto je celkem jednoduché a více si o signálech povíme později.
Pak je definována funkce destroy
, která akorát ukončí aplikaci. Je volána signálem "destroy"
napojeným již dříve.
Zbytek souboru provádí inicializaci pro Gtk a zobrazí GUI.
Tento kód je připravený ke spuštění, takže zkuste použít
Signály jsou klíčovým konceptem programování v Gtk. Kdykoliv se něco stane u nějakého objektu, tak onen objekt vyšle signál. Například, když je kliknuto na tlačítko, vyšle signál "clicked"
. Pokud chcete, aby váš program něco udělal, když tato událost nastane, musíte napojit funkci („obsluhu signálu“) na tento signál. Zde je příklad:
def button_clicked () :
print "you clicked me!"
b = new Gtk.Button ("Click me")
b.connect_after ('clicked', button_clicked)
Poslední dva řádky vytvoří Gtk.Button
nazvané b
a napojí jeho signál clicked
na funkci button_clicked
, která byla definována dříve. Pokaždé, když je kliknuto na tlačítko, provede se kód ve funkci button_clicked
. Ten akorát vypíše zprávu.
Widgety (ovládací prvky, jako jsou tlačítka a popisky) lze v okně uspořádat pomocí kontejnerů. Můžete dohromady kombinovat různé kontejnery, jako jsou boxy nebo mřížky.
Gtk.Window
je samo o sobě kontejner, ale přímo do něj můžete vložit jen jeden widget. My bychom měli rádi dva widgety, obrázek a tlačítko, takže musíme do okna vložit „vysokokapacitní“ kontejner, pro tyto další widgety. Je dostupná řada typů kontejnerů, ale my zde použijeme Gtk.Box
. Ten může obsahovat několik widgetů uspořádaných vodorovně nebo svisle. Složitější rozvržení můžete udělat vložením několika boxů do jiného boxu atd.
Existuje návrhář grafického uživatelského rozhraní nazývaný
Pojďme přidat box a widgety do okna. Vložte následující kód do metody __init__
, hned za řádek window.connect_after
:
box = Gtk.Box()
box.set_spacing (5)
box.set_orientation (Gtk.Orientation.VERTICAL)
window.add (box)
První řádek vytvoří Gtk.Box
nazvaný box
a následující řádky nastaví dvě jeho vlastnosti: orientation
(otočení) je nastavena na svislou (takže widgety jsou uspořádány do sloupce) a spacing
(rozestupy) mezi widgety jsou nastaveny na 5 pixelů. Následující řádek pak přidá nově vytvořený Gtk.Box
do okna.
Zatím okno obsahuje jen prázdný Gtk.Box
a pokud spustíte program nyní, neuvidíte oproti dřívějšku žádné změny (Gtk.Box
je průhledný kontejner, takže jej tam nemůžete vidět).
Pro přidání nějakého widgetu do Gtk.Box
vložte následující kód hned za řádek window.add (box)
:
self.image = Gtk.Image()
box.pack_start (self.image, False, False, 0)
První řádek vytvoří nový Gtk.Image
nazvaný image
, který bude zobrazovat soubor s obrázkem. Protože jej budeme později potřebovat v obsluze signálu, nadefinujeme jej jako proměnou třídy. Musíte přidat image = 0
na začátek třídy GUI
. Po té je widget obrázku přidán (zabalen) do kontejneru box
pomocí metody pack_start
widgetu GtkBox
.
pack_start
přebírá 4 argumenty: widget, který je přidáván do Gtk.Box
(child
); zda by se měl Gtk.Box
zvětšit, když je přidán nový widget (expand
); zda by měl nový widget zabrat všechno vytvořené dodatečné místo, když je Gtk.Box
větší (fill
); jak moc místa, v pixelech, by mělo být mezi widgetem a jeho sousedem uvnitř Gtk.Box
(padding
).
Kontejnery Gtk (a widgety) se dynamicky roztahují, aby zaplnily dostupné místo, pokud jim to tedy dovolíte. Neumisťujte widgety zadáváním přesných souřadnic x,y v okně. Místo toho je umisťujte relativně vůči sobě. To umožní oknu, které se o ně stará, jednodušeji měnit velikost a widgety by tak měli dostat automaticky rozumnou velikost ve většině situací.
Všimněte si také, jak jsou widgety uspořádány do hierarchie. Jakmile jsou zabaleny v Gtk.Box
, je Gtk.Image
považován za potomka Gtk.Box. To umožňuje zacházet se všemi potomky widgetu jako se skupinou. Například byste mohli skrýt Gtk.Box
, což by zároveň skrylo i všechny jeho potomky.
Nyní vložte tyto dva řádky pod ty dva, které jsme již přidali:
button = Gtk.Button ("Open a picture...")
box.pack_start (button, False, False, 0)
Tyto řádky jsou podobné jako první dva, ale tentokrát vytváří Gtk.Button
a přidávají ho do widgetu box
. Všimněte si, že zde nastavujeme argument expand
(ten druhý) na False
, zatímco pro Gtk.Image
byl nastaven na True
. To způsobí, že obrázek zabere všechno dostupné místo a tlačítko jen tolik místa, kolik potřebuje. Když okno maximalizujete, zůstane velikost tlačítka stejná, ale obrázek se zvětší, aby zabral celý zbytek okna.
clicked
od tlačítkaKdyž uživatel klikne na tlačítko
Prvním krokem je napojit signál clicked
od tlačítka na obslužnou funkci signálu, kterou jsem nazvali on_open_clicked
. Vložte tento kód hned za řádek button = Gtk.Button()
, kde bylo tlačítko vytvořeno:
button.connect_after('clicked', self.on_open_clicked)
Tímto se připojí signál clicked
k metodě on_open_clicked
, která bude definována níže.
Nyní vytvoříme metodu on_open_clicked
. Vložte následující do bloku s kódem třídy GUI
za metodu __init__
:
def on_open_clicked (self, button):
dialog = Gtk.FileChooserDialog ("Open Image", button.get_toplevel(), Gtk.FileChooserAction.OPEN);
dialog.add_button (Gtk.STOCK_CANCEL, 0)
dialog.add_button (Gtk.STOCK_OK, 1)
dialog.set_default_response(1)
filefilter = Gtk.FileFilter ()
filefilter.add_pixbuf_formats ()
dialog.set_filter(filefilter)
if dialog.run() == 1:
self.image.set_from_file(dialog.get_filename())
dialog.destroy()
Toto je trochu komplikovanější než vše, o co jsme se doposud pokusili, takže si to pojďme rozebrat:
Řádek začínající dialog
vytvoří dialogové okno SAVE
, pokud by záměrem bylo uložení souboru; transient_for
, která nastaví rodičovské okno dialogového okna.
Následující dva řádky přidají do dialogového okna tlačítka add_button
je celočíselná hodnota, která bude vrácena při zmáčknutí tlačítka: 0 pro
Všimněte si, že používáme standardní názvy tlačítek z Gtk, místo abychom ručně psali „Cancel“ nebo „Open“. Výhodou použití standardních názvů je, že popisky tlačítek budou vždy přeloženy do uživatelova jazyka.
set_default_response
určuje tlačítko, které bude aktivováno, když uživatel dvojitě klikne na soubor nebo zmáčkne
Následující tři řádky omezí dialogové okno Gtk.Image
. Nejprve je vytvořen filtr a pak do něj přidáme všechny druhy souborů podporované v Gdk.Pixbuf
(což zahrnuje většinu obrázkových formátů, včetně PNG a JPEG). Nakonec tento filtr nastavíme aby byl filtrem dialogového okna
dialog.run
zobrazí dialogové okno dialog.run
hodnotu nebo by mohl vrátit , když uživatel klikne na if
.
Předpokládejme, že uživatel klikl na file
v Gtk.Image
na název souboru s obrázkem, který si uživatel vybral. Gtk.Image
vybraný obrázek načte a zobrazí.
Na posledním řádku této metody zlikvidujeme dialogové okno
Všechen kód, který potřebujete, je nyní nachystaný, takže jej můžete zkusit spustit. Tím jste během krátké chvíle získali, co jsme slíbili – plně funkční prohlížeč obrázků (a tím končí naše cesta jazykem Python a knihovnou Gtk).
Pokud v této lekci narazíte na nějaké problémy, porovnejte si svůj kód s tímto ukázkovým kódem.
Zde je pár nápadů, jak byste mohli tuto jednoduchou ukázku rozšířit:
Umožnit uživateli výběr složky místo souboru a poskytnout ovládání pro procházení všech obrázků v této složce.
Použít při načtení obrázku náhodné filtry a efekty a umožnit uživateli takto změněný obrázek uložit.
GEGL poskytuje mocné schopnosti pro práci s obrázky.
Umožnit uživateli načíst obrázky ze síťového sdílení, skenerů a dalších složitějších zdrojů.
Pro práci se síťovými přenosy můžete použít GIO a pro obsluhu skeneru GNOME Scan.