Obsah
1. Grafické uživatelské rozhraní v Pythonu: knihovna Tkinter
4. Základní typy widgetů v knihovně Tk/Tkinter
6. První příklad: zobrazení okna s textem „Hello world!“
8. Druhý příklad: tlačítko reagující na stisk
9. Třetí příklad: použití anonymní funkce pro reakci na stlačení tlačítka
10. Správci umístění (geometrie) widgetů
11. Čtvrtý, pátý a šestý příklad: umístění čtyř tlačítek do mřížky a do jediného sloupce
12. Sedmý, osmý a devátý příklad: prázdná místa v mřížce, spojení buněk mřížky
13. „Přilepení“ widgetů k okrajům buněk mřížky
14. Příklady 11 až 14 – různé varianty „přilepení“ tlačítek k mřížce
15. Repositář s demonstračními příklady
1. Grafické uživatelské rozhraní v Pythonu: knihovna Tkinter
Standardní knihovnou pro tvorbu grafického uživatelského rozhraní v Pythonu je stále Tkinter. Ostatně i jedno ze základních IDE pro Python – IDLE – tuto knihovnu používá (viz dva přiložené screenshoty). Interně se v knihovně Tkinter inicializuje interpret jazyka Tcl sloužící pro ovládání knihovny Tk, ovšem s tímto interním mechanismem se prakticky nemusíme setkat (snad jen v chybových hlášeních, které mohou být z tohoto důvodu někdy dosti kryptické). Největší předností Tkinteru je skutečně snadná a přímočará tvorba grafického uživatelského rozhraní, která je navíc podpořena přímočaře použitelnými správci rozmístění ovládacích prvků (taktéž se setkáme s pojmenováním správci geometrie), což znamená, že se při použití Tkinteru mnohdy obejdeme bez nutnosti používat GUI editory.
Obrázek 1: Jednoduché integrované vývojové prostředí IDLE používá Tkinter.
Důležitá poznámka: na tomto místě je vhodné upozornit na to, že ovládací prvky (widgety) nabízené Tkinterem (a interně tudíž knihovnou Tk), mohou působit poněkud zastarale. Částečné řešení spočívá v náhradě původních widgetů za Ttk (Themed Tk), což také budeme v demonstračních příkladech dodržovat. Widgety nabízené Ttk se od původních widgetů odlišují zejména v tom, že se snaží dodržet zvyklosti panující na konkrétním operačním systému a desktopovém prostředí, kde je aplikace spuštěna. To například znamená, že na Mac OS X se budou widgety chovat odlišně, než na Microsoft Windows či na Linuxu s GNOME. Navíc se u Ttk změnil způsob nastavování vlastností widgetů, který je více konzistentní a do určité míry se podobá kaskádním stylům (CSS) známým z webového světa; naproti tomu původní sada widgetů spíše připomíná explicitní nastavování stylů značek přímo v HTML.
Obrázek 2: Další screenshot integrovaného vývojového prostředí IDLE.
2. Widgety
Základem prakticky všech v současnosti používaných grafických uživatelských rozhraní jsou takzvané widgety, které jsou někdy poněkud nepřesně označovány také jako komponenty. Z pohledu uživatele aplikací s grafickým uživatelským rozhraním se jedná o grafické prvky zobrazené na obrazovce, které mají předem známé chování a předvídatelnou funkci. V mnoha případech je chování widgetů standardizováno či alespoň doporučováno – viz například doporučení pro (dnes již notně zastaralý) Motif, Microsoft Windows, Mac OS a v neposlední řadě také doporučení pro GNOME a KDE. Velká část widgetů se snaží svým vzhledem do jisté míry reflektovat objekty z reálného světa (tlačítka, „teploměry“, přepínače programů, objekty známé z papírových formulářů apod.). Z pohledu programátora je naproti tomu widget objektem, kterému lze nastavit určitý stav a který reaguje na události, které při své práci generuje uživatel (přesouvání objektů na obrazovce, stlačování obrazů tlačítek pomocí myši či stylusu, psaní textu, gesta na dotykové obrazovce atd.).
3. Kontejnery
Samotné widgety nejsou na obrazovce prakticky nikdy zcela osamocené, ostatně většina knihoven pro GUI by samostatný widget nedokázala zobrazit. Ve skutečnosti se téměř vždy nachází v nějakém okně, dialogu či dalším nadřazeném widgetu. Programátoři grafických uživatelských rozhraní se často setkají s pojmem kontejner. Jedná se o komponentu, na kterou lze vkládat různé widgety a mnohdy i další kontejnery. Obecně tak interně vzniká stromová datová struktura jejíž kořen je představován plochou na obrazovce, na které jsou umístěna okna aplikací (dnes je ovšem i samotná plocha obrazovky součástí větší virtuální plochy zobrazované obecně na více monitorech). V těchto oknech se dále nachází kontejnery a widgety. V mnoha grafických uživatelských rozhraních přitom mohou být vybrané widgety (zdaleka ne však všechny) současně i kontejnery. Kontejnery kromě jiného řeší i rozmístění widgetů na své ploše.
Způsobů pro rozmisťování widgetů do kontejnerů existuje více. Základní dělení je na kontejnery, kde jsou widgety umisťovány absolutně (do této kategorie patří WinAPI, MFC, OWL a VCL) a naopak kontejnery, které widgety většinou umisťují podle své velikosti a vzájemných vztahů (zde se nachází javovské AWT, Swing, GTK, Qt, Tk/Tkinter a mnoho dalších). V toolkitu Tk a tím pádem i v Tkinteru se mohou widgety umisťovat několika různými způsoby (pack, place a grid).
4. Základní typy widgetů v knihovně Tk/Tkinter
V průběhu mnoha let se množina widgetů používaných v různých grafických uživatelských rozhraních postupně rozšiřovala, ostatně postačí se podívat na obrázky z prvních grafických rozhraní navržených ve společnosti Xerox a porovnat je s moderním desktopem. Současně však také docházelo ke sjednocování vzhledu jednotlivých widgetů i jejich chování na různých platformách. Vzhled samozřejmě není na všech platformách přesně stejný, to však pro uživatele většinou nemusí představovat významnější praktický problém, na rozdíl od odlišného chování celého prostředí i jednotlivých widgetů.
V toolkitu Tk je k dispozici poměrně velké množství widgetů, podobně jako v dalších moderních toolkitech. Navíc dnes widgety existují ve dvou podobách – starší (původní) a novější (Ttk neboli „themed Tk“), které lépe odpovídají požadavkům uživatelů současných desktopových prostředí a jejichž vzhled a chování se může od původních widgetů odlišovat. V následující tabulce je uveden seznam základních typů widgetů. Pro mnoho aplikací je níže uvedená skupina widgetů dostačující, avšak v případě, že aplikace potřebuje vytvořit nový widget, je to samozřejmě možné, protože knihovna Tk je navržena tak, že ji lze poměrně jednoduchým způsobem rozšiřovat. V následující tabulce si také můžete všimnout toho, že některé widgety jsou pojmenovány odlišným způsobem od dnes používané terminologie. Vychází to z faktu, že Tcl/Tk je mnohem starší než většina dnešních toolkitů.
Jméno widgetu | Význam a funkce |
---|---|
label | widget, který zobrazuje v okně či dialogu měnitelný text |
button | graficky zobrazené tlačítko, které implicitně reaguje na levé tlačítko myši |
checkbutton | dvoustavový přepínač, který implicitně reaguje na levé tlačítko myši |
radiobutton | widget, jichž může být sdruženo větší množství, vždy pouze jeden je vybraný |
scale | dnes nazýván pojmem slider atd., jedná se o widget s posuvnou částí a přidruženým textem, kde se zobrazuje hodnota v závislosti na poloze posuvné části |
entry | widget, do kterého je možné zapisovat text, k tomu má přidruženo mnoho klávesových zkratek (jde o kombinaci staršího a novějšího standardu) |
spinbox | widget určený pro zadávání číselných hodnot kombinací klávesnice a myši (i s kontrolou mezí) |
menu | vertikální menu, které se skládá z více položek |
menubutton | používá se spolu s menu pro vytváření jednotlivých položek |
listbox | widget, jež nabízí na výběr libovolné množství řádků s textem |
scrollbar | podobné widgetu scale s tím rozdílem, že zobrazuje posuvné šipky a naopak nezobrazuje přidruženou číselnou hodnotu |
frame | jeden z několika nabízených kontejnerů; tento má tvar obdélníka (může být také neviditelný nebo může mít 3D rámeček) |
toplevel | další z kontejnerů, tento se chová jako samostatné okno či dialog |
bitmap | bitmapa, tj. rastrový obrázek |
photo/photoimage | rastrový obrázek, jež může být načten z externího souboru v mnoha různých formátech |
canvas | widget, na který lze programově vkládat další grafické komponenty (úsečky, oblouky, kružnice, polyčáry, text atd.) |
Výše zmíněné widgety budou podrobněji popsány v navazujícíh částech tohoto seriálu. Zde se pouze chci zmínit o pěkně pojatých menu. Jednotlivá vertikální menu se totiž mohou od mateřského okna „odpoutat“ a chovat se jako samostatné okno či dialog. Díky tomu lze celou aplikaci zachovat po grafické stránce velmi kompaktní a nechat na uživateli, zda a kdy si jednotlivá menu zobrazí v samostatných oknech. Aplikace přitom může používat jak hlavní menu, tak i libovolné množství menu příručních (kontextových, pop-up). Podobný způsob práce s menu je k vidění například u textového editoru Vim (ovšem pouze v některých prostředích) nebo v grafickém editoru MtPaint.
5. Vlastnosti widgetů
Ke každému widgetu je možné nastavit mnoho různých vlastností, které mění buď jeho vizuální vzhled na obrazovce počítače nebo jeho chování, tj. způsob reakce widgetu na akce uživatele. Mezi tyto akce počítáme například kliknutí tlačítkem myši, použití klávesových zkratek (hot keys), přesunutí widgetu atd. Některé vlastnosti jsou všem widgetům společné, další vlastnosti jsou však jedinečné pro jeden či pouze několik typů widgetů. Je to ostatně logické, některé widgety mají speciální chování. Vlastnosti lze nastavovat již při vytváření widgetů, na druhou stranu je také možné vlastnosti měnit až při běhu aplikace. Způsob nastavení vlastností si ukážeme na demonstračních příkladech. V následující tabulce jsou uvedeny vlastnosti, které jsou společné prakticky všem widgetům (kromě speciálních widgetů typu „položka menu“, které mají vlastnosti omezeny, stejně tak jako jejich reakce na uživatelovu činnost). Pozor! – při použití Ttk se nastavování vizuálních vlastností musí provádět přes styly, což si samozřejmě taktéž ukážeme:
Jméno vlastnosti | Popis vlastnosti |
---|---|
background | barva pozadí widgetu v případě, že widget není aktivní (vybraný) |
foreground | barva popředí widgetu (například zobrazeného textu) v případě, že widget není aktivní (vybraný) |
borderwidth | šířka okraje widgetu, která je zadaná v pixelech |
activebackground | barva pozadí widgetu v případě, že je widget vybrán (typicky kurzorem myši) |
activeforeground | barva popředí widgetu v případě, že je widget vybrán |
disabledforeground | barva popředí widgetu v případě, že je ovládání widgetu zakázáno |
relief | způsob prostorového zobrazení widgetu |
compound | způsob umístění bitmapy či obrázku na widgetu |
bitmap | bitmapa, která má být ve widgetu zobrazena |
image | obrázek, který má být ve widgetu zobrazen (více o bitmapách a obrázcích bude uvedeno v dalších dílech) |
font | jméno fontu, který je použit pro text uvnitř widgetu (font lze specifikovat platformově nezávislým způsobem) |
text | text, který má být ve widgetu (tlačítko, položka menu atd.) zobrazen |
cursor | jméno kurzoru myši, který bude použit v případě, že se kurzor nachází nad widgetem |
textvariable | jméno proměnné, která je nastavována podle uživatelových manipulací s widgetem (StringVar v Tkinteru) |
justify | zarovnání textu ve widgetu v případě, že se zobrazuje více řádků |
anchor | způsob umístění textu či obrázku ve widgetu |
Vlastnosti se nastavují dvěma způsoby – u původních widgetů přímo nastavením vlastnosti (například background=„red“) u „themed Tk“ pak změnou takzvaných stylů, což je sice nepatrně složitější, ovšem mnohem flexibilnější způsob.
6. První příklad: zobrazení okna s textem „Hello world!“
Prakticky nejjednodušším příkladem je zobrazení okna s×textovou informací neboli návěštím (label). Tuto úlohu, kterou jsme si ostatně již ukazovali v úvodním článku pro mnoho různých toolkitů, je možné řešit tak, že se nejprve vytvoří okno (toplevel widget) a do něho se vloží widget typu label, který požadovanou textovou informaci zobrazuje. K dispozici přitom máme dva typy tohoto widgetu – jak původní z knihovny Tk, tak i návěští z Ttk:
#!/usr/bin/env python from tkinter import * from tkinter import ttk root = Tk() label = ttk.Label(root, text="Hello world!") label.pack() root.mainloop()
Na řádku:
root = Tk()
je vytvořeno okno a současně je mu interně přiřazen interpret jazyka Tcl, přes který se všechny GUI operace provádí (se samotným Tcl však do styku nemusíme přijít).
Na následujícím řádku:
label = ttk.Label(root, text="Hello world!")
je vytvořeno textové návěští a je přiřazeno k vytvořenému oknu.
Další řádek je velmi důležitý, protože se zde používá takzvaný správce geometrie pack. Správci geometrie jsou používáni pro umisťování widgetů do okna. Konkrétně správce pack dokáže widgety umisťovat horizontálně či vertikálně, takže je jeho použití velmi jednoduché (a současně má tento správce hodně omezení).
Poslední řádek spustí interní smyčku, v níž se postupně získávají a zpracovávají události z fronty událostí. Taková smyčka se většinou nazývá event loop:
root.mainloop()
Obrázek 3: Spuštění příkladu v Linuxu (Fluxbox).
Příklad ve skutečnosti není úplný, protože není naprogramováno uzavření okna. Tento problém vyřešíme tak, že do okna vložíme další widget, tentokrát typu button. Po stlačení tohoto tlačítka se okno korektně uzavře. Nejprve si však musíme vysvětlit koncept událostí (events)
Obrázek 4: Díky tomu, že je toolkit Tk použitelný i v dnes již zastaralých systémech, lze stejný příklad spustit například i na obstarožních Windows XP.
7. Události a reakce na ně
Při programování grafických uživatelských rozhraní je často používán pojem události (event(s)). Událostmi řízené programování je ostatně s programováním GUI prakticky neoddělitelně spojeno. Každý widget může v průběhu svého života generovat nějaké události. Naprostá většina událostí vzniká tak, že uživatel s widgetem interaktivně pracuje (například stlačí tlačítko zobrazené na obrazovce). Ke každému widgetu je příslušná jedna „implicitní“ událost, na kterou reaguje. Tato událost se nastavuje pomocí změny vlastnosti widgetu, což bude ukázáno v demonstračních příkladech v následujících kapitolách. Kromě implicitní události lze na widgety navázat i další události, například tlačítko (button) může reagovat i na stlačení klávesy na klávesnici, na pravé tlačítko myši či na rolování kolečkem myši. Toto navázání se provádí pomocí příkazu bind, který obsahuje množství voleb. Musíme si však uvědomit, že některé události se na různých operačních systémech a desktopových prostředích mohou generovat různým způsobem – typicky se jedná o přesun fokusu.
8. Druhý příklad: tlačítko reagující na stisk
V dnešním druhém demonstračním příkladu přidáme do okna další ovládací prvek (widget). Bude se jednat o tlačítko, které bude reagovat na svůj stisk, což je jedna ze základních uživatelem vyvolaných událostí, které mohou v GUI vzniknout. Při vytváření tlačítka můžeme přes nepovinný pojmenovaný parametr command určit, která funkce se při stisku tlačítka zavolá (jedná se tedy o takzvanou callback funkci):
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys def exit(): sys.exit(0) root = Tk() label = ttk.Label(root, text="Hello world!") button = ttk.Button(root, text="Close window", command=exit) label.pack() button.pack() root.mainloop()
Obrázek 5: Spuštění druhého příkladu ve Fluxboxu (vzhled ovládacích prvků Tkinteru je poměrně strohý, bez grafických efektů).
Obrázek 6: Běh na Windows.
9. Třetí příklad: použití anonymní funkce pro reakci na stlačení tlačítka
Pozor si musíte dát na to, že se předává skutečně jen jméno funkce (zde exit) a nikoli její parametry. Pokud byste za jméno zapsali kulaté závorky s parametry, funkce by se již při konstrukci tlačítka zavolala a použila by se její návratová hodnota, což většinou není takové chování, jaké požadujeme.
Vzhledem k tomu, že mnoho reakcí na události je velmi jednoduchých, vedlo by vytváření zvláštních funkcí pro každou událost ke zbytečně rozsáhlému kódu. V Pythonu však můžeme použít i jednodušší formu anonymních funkcí (oproti plnohodnotným anonymním funkcím mohou obsahovat výraz, nikoli však řídicí bloky), takže předchozí příklad lze přepsat následovně:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() label = ttk.Label(root, text="Hello world!") button = ttk.Button(root, text="Close window", command=lambda: sys.exit(0)) label.pack() button.pack() root.mainloop()
Obrázek 7: Spuštění třetího příkladu ve Fluxboxu (screenshot by měl být totožný s obrázkem číslo 3).
10. Správci umístění (geometrie) widgetů
Existují dva základní způsoby, jakými lze vkládat widgety do okna či dialogu. První možností, která byla použita zejména v aplikacích tvořených pomocí WinAPI (Windows API) a MFC (Microsoft Foundation Classes), je absolutní umisťování, například specifikací souřadnic levého horního rohu widgetu a jeho šířky a výšky. Tato možnost je dobře použitelná pouze pro ty aplikace, které mají běžet na jedné platformě s jedním správcem oken. Pro multiplatformní aplikace, u nichž není dopředu známá přesná velikost oken ani rozlišení obrazovky, se často používá druhá možnost, při které jsou widgety umisťováni buď relativně vůči sobě nebo do flexibilních mřížek či dalších tvarů – tento způsob využívají prakticky všechny modernější knihovny widgetů, jakými jsou Qt, GTK i Swing.
Oba dva výše zmíněné způsoby jsou v knihovně Tkinter podporovány, používat by se však měl především způsob druhý, tj. relativní umisťování widgetů. Pro umisťování jednotlivých widgetů do okna jsou v Tkinter používáni takzvaní správci (manažeři) geometrie. K dispozici je několik typů těchto správců. V předchozích příkladech jsme používali správce pack, ovšem velmi užitečný je i správce grid.
Poznámka: jméno manažeru grid sice může připomínat například GridLayout z Javy, ovšem Tkinterovská varianta je mnohem jednodušeji použitelná a současně i více flexibilní.
11. Čtvrtý, pátý a šestý příklad: umístění čtyř tlačítek do mřížky a do jediného sloupce
S použitím manažeru grid se widgety umisťují do neviditelné mřížky. Velikost mřížky je automaticky měněna tak, aby se do ní všechny vkládané widgety umístily v „rozumné“ velikosti. Programově je však možné měnit vzdálenost mezi jednotlivými widgety a tím také měnit velikost mřížky. V dalším demonstračním příkladu jsou do okna umístěny čtyři tlačítka (widgety typu button) do jedné mřížky 2×2 buňky:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button") button2 = ttk.Button(root, text="Second button") button3 = ttk.Button(root, text="Third button") button4 = ttk.Button(root, text="Fourth button") button1.grid(column=1, row=1) button2.grid(column=2, row=1) button3.grid(column=1, row=2) button4.grid(column=2, row=2) root.mainloop()
Obrázek 8: Čtvrtý demonstrační příklad.
Umístění tlačítek je patrné z dalšího screenshotu. Všimněte si, že bez dalšího explicitního nastavení je každé tlačítko pouze tak velké, aby se do něj vešel zadaný text.
K tlačítkům samozřejmě můžeme přiřadit nějakou akci vyvolanou jejich stlačením:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="Fourth button", command=lambda: sys.exit(0)) button1.grid(column=1, row=1) button2.grid(column=2, row=1) button3.grid(column=1, row=2) button4.grid(column=2, row=2) root.mainloop()
Obrázek 9: Čtvrtý demonstrační příklad.
Pokud bychom tlačítka umístili do okna manažerem pack, vypadal by výsledek odlišně, i když by se aplikace chovala stejně:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button") button2 = ttk.Button(root, text="Second button with long text") button3 = ttk.Button(root, text="Third button") button4 = ttk.Button(root, text="Fourth button") button1.pack() button2.pack() button3.pack() button4.pack() root.mainloop()
Obrázek 10: Použití správce geometrie pack.
12. Sedmý, osmý a devátý příklad: prázdná místa v mřížce, spojení buněk mřížky
Můžeme si také vyzkoušet změnit umístění jednotlivých tlačítek v mřížce. Pokud není do nějaké buňky mřížky vložen widget, je tato plocha prázdná:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button") button2 = ttk.Button(root, text="Second button") button3 = ttk.Button(root, text="Third button") button4 = ttk.Button(root, text="Fourth button") button1.grid(column=2, row=4) button2.grid(column=3, row=1) button3.grid(column=1, row=3) button4.grid(column=4, row=2) root.mainloop()
Obrázek 11: Čtyři tlačítka v pomyslné mřížce 4×4 buňky.
Opět můžeme k tlačítkům přiřadit nějakou akci vyvolanou jejich stlačením:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="Fourth button", command=lambda: sys.exit(0)) button1.grid(column=2, row=4) button2.grid(column=3, row=1) button3.grid(column=1, row=3) button4.grid(column=4, row=2) root.mainloop()
Obrázek 12: Čtyři tlačítka v pomyslné mřížce 4×4 buňky.
Navíc lze widgety pomocí parametrů columnspan a rowspan nastavit tak, aby obsadily více sousedních buněk (pokud se ovšem widgety nezvětší na celou plochu buňky, nebude toto nastavení vždy viditelné):
from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="First button", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="Fourth button", command=lambda: sys.exit(0)) button1.grid(column=1, row=1) button2.grid(column=2, row=2) button3.grid(column=1, row=3, columnspan=2) button4.grid(column=4, row=1, rowspan=3) root.mainloop()
Obrázek 13: Tlačítka přesahující přes několik buněk.
13. „Přilepení“ widgetů k okrajům buněk mřížky
Widget je možné „přilepit“ k vybraným okrajům buňky (či buněk), a to konkrétně pomocí vlastnosti nazvané sticky. V nejjednodušším případě se této vlastnosti přiřazuje řetězec, který může obsahovat libovolnou kombinaci písmen n (north), s (south), e (east) nebo w (west). Widget je po zadání této vlastnosti přilepen ke specifikovaným okrajům buňky, což mj. může znamenat, že dojde k jeho zvětšení.
14. Příklady 11 až 14 – různé varianty „přilepení“ tlačítek k mřížce
V této kapitole si ukážeme, jak lze modifikovat následující příklad, v němž je zobrazena čtveřice tlačítek v mřížce 2×2 buňky:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="1st btn", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="This is fourth button, the last one", command=lambda: sys.exit(0)) button1.grid(column=1, row=1) button2.grid(column=2, row=1) button3.grid(column=1, row=2) button4.grid(column=2, row=2) root.mainloop()
Obrázek 14: Implicitně jsou tlačítka v buňkách pouze vycentrována.
Všechna tlačítka jsou „přilepena“ k západnímu (tedy levému) okraji svých buněk:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="1st btn", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="This is fourth button, the last one", command=lambda: sys.exit(0)) button1.grid(column=1, row=1, sticky="w") button2.grid(column=2, row=1, sticky="w") button3.grid(column=1, row=2, sticky="w") button4.grid(column=2, row=2, sticky="w") root.mainloop()
Obrázek 15: Přilepení tlačítek k západnímu (levému) okraji buněk.
Všechna tlačítka jsou „přilepena“ k východnímu (tedy pravému) okraji svých buněk:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="1st btn", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="This is fourth button, the last one", command=lambda: sys.exit(0)) button1.grid(column=1, row=1, sticky="e") button2.grid(column=2, row=1, sticky="e") button3.grid(column=1, row=2, sticky="e") button4.grid(column=2, row=2, sticky="e") root.mainloop()
Obrázek 16: Přilepení tlačítek k východnímu (pravému) okraji buněk.
Všechna tlačítka jsou „přilepena“ jak k západnímu, tak i k východnímu okraji, což mj. znamená, že pod sebou ležící tlačítka mají shodnou šířku:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="1st btn", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="This is fourth button, the last one", command=lambda: sys.exit(0)) button1.grid(column=1, row=1, sticky="we") button2.grid(column=2, row=1, sticky="we") button3.grid(column=1, row=2, sticky="we") button4.grid(column=2, row=2, sticky="we") root.mainloop()
Obrázek 17: Výplň celé buňky tlačítky, které jsou přilepené k západní i východní straně.
Poslední tlačítko obsazuje celý třetí sloupec mřížky a je navíc přilepeno k severnímu (hornímu) i jižnímu (spodnímu) okraji:
#!/usr/bin/env python from tkinter import * from tkinter import ttk import sys root = Tk() button1 = ttk.Button(root, text="1st btn", command=lambda: sys.exit(0)) button2 = ttk.Button(root, text="Second button", command=lambda: sys.exit(0)) button3 = ttk.Button(root, text="Third button", command=lambda: sys.exit(0)) button4 = ttk.Button(root, text="This is fourth button, the last one", command=lambda: sys.exit(0)) button1.grid(column=1, row=1, sticky="we") button2.grid(column=2, row=2, sticky="we") button3.grid(column=1, row=3, sticky="we") button4.grid(column=3, row=1, rowspan=4, sticky="nswe") root.mainloop()
Obrázek 18: Čtvrté tlačítko používá „přilepení“ ke všem stranám spojené buňky.
15. Repositář s demonstračními příklady
Zdrojové kódy všech dnešních demonstračních příkladů naleznete pod následujícími odkazy:
Obrázek 19: Způsob změny stylu ovládacích prvků jak přímo, tak i s využitím stylů si popíšeme příště.
Obrázek 20: Ukázka dalších základních widgetů.
16. Odkazy na Internetu
- TkDocs: Styles and Themes
http://www.tkdocs.com/tutorial/styles.html - Drawing in Tkinter
http://zetcode.com/gui/tkinter/drawing/ - Changing ttk widget text color (StackOverflow)
https://stackoverflow.com/questions/16240477/changing-ttk-widget-text-color - Hra Breakout napísaná v Tkinteri
https://www.root.cz/clanky/hra-breakout-napisana-v-tkinteri/ - The Hitchhiker's Guide to Pyhton: GUI Applications
http://docs.python-guide.org/en/latest/scenarios/gui/ - 7 Top Python GUI Frameworks for 2017
http://insights.dice.com/2014/11/26/5-top-python-guis-for-2015/ - GUI Programming in Python
https://wiki.python.org/moin/GuiProgramming - Cameron Laird's personal notes on Python GUIs
http://phaseit.net/claird/comp.lang.python/python_GUI.html - Python GUI development
http://pythoncentral.io/introduction-python-gui-development/ - Graphic User Interface FAQ
https://docs.python.org/2/faq/gui.html#graphic-user-interface-faq - TkInter
https://wiki.python.org/moin/TkInter - Tkinter 8.5 reference: a GUI for Python
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html - TkInter (Wikipedia)
https://en.wikipedia.org/wiki/Tkinter - appJar
http://appjar.info/ - appJar (Wikipedia)
https://en.wikipedia.org/wiki/AppJar - appJar na Pythonhosted
http://pythonhosted.org/appJar/ - Stránky projektu PyGTK
http://www.pygtk.org/ - PyGTK (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PyGObject
https://wiki.gnome.org/Projects/PyGObject - Stránky projektu Kivy
https://kivy.org/#home - Stránky projektu PyQt
https://riverbankcomputing.com/software/pyqt/intro - PyQt (Wikipedia)
https://cs.wikipedia.org/wiki/PyGTK - Stránky projektu PySide
https://wiki.qt.io/PySide - PySide (Wikipedia)
https://en.wikipedia.org/wiki/PySide - Stránky projektu Kivy
https://kivy.org/#home - Kivy (framework, Wikipedia)
https://en.wikipedia.org/wiki/Kivy_(framework) - QML Applications
http://doc.qt.io/qt-5/qmlapplications.html - KDE
https://www.kde.org/ - Qt
https://www.qt.io/ - GNOME
https://en.wikipedia.org/wiki/GNOME - Category:Software that uses PyGTK
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGTK - Category:Software that uses PyGObject
https://en.wikipedia.org/wiki/Category:Software_that_uses_PyGObject - Category:Software that uses wxWidgets
https://en.wikipedia.org/wiki/Category:Software_that_uses_wxWidgets - GIO
https://developer.gnome.org/gio/stable/ - GStreamer
https://gstreamer.freedesktop.org/ - GStreamer (Wikipedia)
https://en.wikipedia.org/wiki/GStreamer - Wax Gui Toolkit
https://wiki.python.org/moin/Wax - Python Imaging Library (PIL)
http://infohost.nmt.edu/tcc/help/pubs/pil/