Hlavní navigace

Programovací jazyk TCL (5)

16. 8. 2005
Doba čtení: 10 minut

Sdílet

Dnes se budeme zabývat knihovnou (a současně i toolkitem) jménem Tk, která slouží k jednoduchému a zároveň rychlému návrhu grafického uživatelského rozhraní (GUI). Nejdříve si uvedeme základní informace o charakteristických grafických prvcích, ze kterých se skládá grafické uživatelské rozhraní. Posléze si ukážeme práci s widgety a kontejnery, které jsou knihovnou Tk nabízeny.

Obsah

1. Úvodní informace o knihovně Tk
2. Widgety a kontejnery
3. Základní typy widgetů v knihovně Tk
4. Vlastnosti widgetů
5. Události
6. Demonstrační příklady se základními widgety
7. Demonstrační příklady na práci s manažery umístění (geometrie)
8. Obsah dalšího pokračování tohoto seriálu

1. Úvodní informace o knihovně Tk

Tk je toolkit (z pohledu programovacího jazyka se přitom jedná o knihovnu či – jinými slovy řečeno – modul) určený pro jednoduchý a rychlý vývoj programů obsahujících grafické uživatelské rozhraní (Graphical User Interface – GUI). Autorem tohoto toolkitu je, podobně jako v případě programovacího jazyka Tcl, John Ousterhout, mezi jehož zájmy v minulosti patřila automatizace (skriptovatelnost) aplikací a právě tvorba grafických uživatelských rozhraní. V minulosti byl tento toolkit velmi oblíbený, proto se dodával (a stále dodává) spolu s instalací programovacího jazyka Tcl. I z tohoto důvodu se také v různých materiálech a dokumentech často setkáme se společným názvem Tcl/Tk. Samotný název Tk jednoduše znamená zkratku slovaToolKit. Udává se, že poměr psaného kódu v Tcl/Tk je vůči Motifu na hodnotách 1:20 a vůči základnímu Xlibu dokonce 1:100! (vše se samozřejmě týká tvorby grafického uživatelského rozhraní).

V průběhu postupného vývoje novějších (avšak ne nutně dokonalejších) programovacích nástrojů byla knihovna Tk použita v mnoha dalších programovacích jazycích. Pravděpodobně nejznámější je, samozřejmě kromě samotné dvojice Tcl/Tk, modul pro programovací jazyk Perl (Perl/Tk) a Python (Tkinter – Tk Interface), knihovnu Tk je však samozřejmě možné použít i v dalších programovacích jazycích, i když v mnoha případech ne tak snadně a efektivně jako ze samotného Tcl. V praxi se často s výhodou používá spojení programů napsaných v programovacím jazyku C či s C++ s grafickým uživatelským rozhraním, které je vytvořeno pomocí Tcl a Tk.

2. Widgety a kontejnery

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 Motif, Microsoft Windows a nověji také doporučení pro poměrně nové Gnome a KDE. Velká část widgetů se snaží svým vzhledem 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, jemuž lze nastavit určitý stav a jenž 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 atd.).

Samotné widgety nejsou na obrazovce prakticky nikdy zcela osamocené – ve skutečnosti se téměř vždy nacházejí 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 (Root :-)) je představován plochou na obrazovce, na které jsou umístěna okna aplikací. V těchto oknech se dále nacházejí kontejnery a widgety. V mnoha grafických uživatelských rozhraních přitom mohou být vybrané widgety (zdaleka však ne 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í 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 (zde se nachází AWT, Swing, GTK, Qt, Tk a mnoho dalších).

V toolkitu Tk se mohou widgety umisťovat několika různými způsoby (pack, place a grid), které si podrobněji popíšeme v šestém pokračování tohoto seriálu.

3. Základní typy widgetů v knihovně Tk

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 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 nepředstavuje významnější problém, na rozdíl od odlišného chování celého prostředí i jednotlivých widgetů, na rozdíl od chování widgetů).

V toolkitu Tk je k dispozici poměrně velké množství widgetů, podobně jako v dalších moderních toolkitech. 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ů.

Základní typy widgetů v knihovně Tk
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 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 popsány v dalších čá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).

4. 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ávesnice (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 své reakce na uživatelovu činnost). Při programovém nastavení vlastnosti widgetu se před název vlastnosti přidává znak mínus: „-“.

Společné vlastnosti widgetů
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
disabledforegrou­nd 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
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

5. Události

Při programování grafických uživatelských rozhraní je často používán pojem události (event) – 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 stiskne 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 dvou 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 stisknutí 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 mohou generovat různým způsobem – typicky se jedná o přesun fokusu. I událostmi se budeme podrobněji zabývat v dalších částech tohoto seriálu.

6. Demonstrační příklady se základními widgety

V této kapitole budou ukázány jednoduché demonstrační příklady. Jejich spouštění je možné provádět z vizuálního shellu wish. Při spuštění tohoto shellu je již zobrazeno okno, do kterého je možné vkládat jak kontejnery, tak i jednotlivé widgety. Toto okno se tedy nemusí vytvářet programově.

Prakticky nejjednodušším příkladem je zobrazení okna s textovou informací. Tuto úlohu lze řešit tak, že se do okna vloží widget typu label, který požadovanou textovou informaci zobrazuje:

#!/usr/bin/wish
label .hello -text "Hello world!"
pack .hello 

Na prvním obrázku je zobrazeno okno prvního demonstračního příkladu.

TCL 5 - 1

Obrázek 1: screenshot prvního demonstračního příkladu

Výše uvedený příklad 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 stisknutí tohoto tlačítka se okno korektně uzavře:

#!/usr/bin/wish
label .hello -text "Hello world!"
button .close -text "Close window" -command {exit}
pack .hello
pack .close 

Okno tohoto demonstračního příkladu je ukázáno na druhém obrázku.

TCL 5 - 2

Obrázek 2: screenshot druhého demonstračního příkladu

V příkladu lze samozřejmě měnit vlastnosti jednotlivých widgetů, například následovně:

#!/usr/bin/wish
label .hello -text "Hello world!"
button .close -text "Close window" -command {exit} -background red -activebackground green
pack .hello
pack .close 

7. Demonstrační příklady na práci s manažery umístění (geometrie)

Nejjednodušším manažerem používaným pro umisťování widgetů je manažer grid. S použitím tohoto manažeru 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 příkladu jsou do okna umístěny čtyři tlačítka (widgety typu button) do jedné mřížky:

#!/usr/bin/wish
button .prvni -text "First button" -command {exit}
button .druhy -text "Second button" -command {exit}
button .treti -text "Third button" -command {exit}
button .ctvrty -text "Fourth button" -command {exit}
grid .prvni -column 1 -row 1
grid .druhy -column 2 -row 1
grid .treti -column 1 -row 2
grid .ctvrty -column 2 -row 2 

Umístění tlačítek je patrné ze třetího obrázku. 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.

TCL 5 - 3

Obrázek 3: screenshot třetího demonstračního příkladu

Můžeme si také vyzkoušet změnit umístění jednotlivých tlačítek v mřížce:

#!/usr/bin/wish
button .prvni -text "First button" -command {exit}
button .druhy -text "Second button" -command {exit}
button .treti -text "Third button" -command {exit}
button .ctvrty -text "Fourth button" -command {exit}
grid .prvni -column 2 -row 4
grid .druhy -column 3 -row 1
grid .treti -column 1 -row 3
grid .ctvrty -column 4 -row 2 

Výsledek takto modifikovaného příkladu je patrný ze čtvrtého obrázku.

TCL 5 - 4

Obrázek 4: screenshot čtvrtého demonstračního příkladu

root_podpora

8. Obsah dalšího pokračování tohoto seriálu

V dalším pokračování tohoto seriálu budou podrobněji popsány nejpoužívanější widgety, které jsou knihovnou Tk uživatelům i programátorům nabízeny. Také si ukážeme různé způsoby umisťování widgetů pomocí manažerů geometrie.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.