Hlavní navigace

Programovací jazyk TCL (17)

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

Sdílet

V dnešním pokračování seriálu pojednávajícím o programovacím jazyku Tcl se budeme zabývat prací s knihovnou BWidgets, která programátorům nabízí widgety rozšiřující původní sadu widgetů z toolkitu Tk. Podrobněji si popíšeme widgety určené pro tvorbu příkazových tlačítek, kombo boxů, zobrazení stromové struktury a také vytvoření stavového řádku libovolného okna.

Obsah

1. Widget Button
2. Stavový řádek u libovolného okna
3. Zobrazení stromové struktury
4. Widget ComboBox
5. Výběr barvy pomocí dialogu
6. Obsah dalšího pokračování tohoto seriálu

1. Widget Button

Základem prakticky všech dialogových oken i toolbarů jsou příkazová tlačítka, tj. takové ovládací prvky grafického uživatelského rozhraní, po jejichž stisknutí se provede nějaká předem naprogramovaná akce – nejčastěji se jedná o zavolání takzvané callback funkce. V knihovněBWid­gets je příkazové tlačítko reprezentováno widgetem nazvaným jednoduše Button. Při vytváření tlačítka je možné jeho vizuální vzhled i chování ovlivnit poměrně velkým množstvím voleb, které jsou uvedeny v následující tabulce:

Volby widgetu Button
Název volby Význam
-activebackground barva pozadí aktivního tlačítka
-activeforeground barva popředí aktivního tlačítka
-anchor umístění textu či obrázku v tlačítku
-background barva pozadí neaktivního tlačítka
-bitmap bitmapa (monochromatická) na tlačítku
-borderwidth šířka okraje tlačítka
-cursor jeden z předdefinovaných názvů kurzorů
-disabledforeground barva pozadí zakázaného tlačítka
-font font textu na tlačítku
-foreground barva popředí neaktivního tlačítka
-image rastrový obrázek zobrazený místo textu či vedle textu
-justify zarovnání textu a obrázku na tlačítku
-padx rozšíření tlačítka v horizontálním směru
-pady rozšíření tlačítka ve vertikálním směru
-repeatdelay doba pro spuštění automatického opakování (vhodné jen pro některé akce)
-repeatinterval počet milisekund mezi jednotlivými opakováními
-takefocus volba, zda tlačítko akceptuje změnu fokusu přes klávesnici
-text text zobrazený na tlačítku
-textvariable proměnná, jejíž obsah je zobrazen na tlačítku místo statického textu
-armcommand funkce volaná v případě stlačení levého tlačítka myši
-command funkce volaná v případě puštění levého tlačítka myši
-default povolení či zakázání tlačítka
-disarmcommand funkce volaná v případě puštění levého tlačítka myši (voláno před -command)
-height výška tlačítka
-helptext text bublinové nápovědy k tlačítku
-helptype typ bublinové nápovědy k tlačítku
-helpvar jméno proměnné, která je použita při zobrazení nápovědy
-name jméno tlačítka
-relief 3D vzhled tlačítka. Je povolena i speciální hodnota flat
-state změna stavu tlačítka (normální, aktivní, zakázané)
-underline index znaku v textu na tlačítku, který má být podtržen
-width šířka tlačítka

V prvním demonstračním příkladu je ukázáno, jakým způsobem je možné v okně vytvořit příkazové tlačítko. Kromě specifikace textu zobrazeného na tlačítku je přidán i text bublinové nápovědy (ta se zobrazí v případě, že se nad tlačítkem po krátký časový interval zastaví kurzor myši) a příkaz, který se vyvolá ihned po stisknutí levého tlačítka myši. Všimněte si značně rozdílného chování voleb -command a -armcommand. První volba slouží k registraci callback funkce volané v případě, že je nad widgetem puštěno levé tlačítko myši, druhá volba naopak slouží k zadání callback funkce volané ihned při stisknutí levého tlačítka myši. První volba je sice v současných grafických uživatelských rozhraních používána častěji (umožňuje mimo jiné zrušit zadaný příkaz tím, že kurzor opustí hranice tlačítka), v některých případech (například skrolovací tlačítka) je však výhodnější používat volbu druhou. Mimo to je možné použít i příkaz -disarmcommand, kterým se registruje callback funkce zavolaná při puštění levého tlačítka myši i v případě, že kurzor myši opustil oblast příkazového tlačítka.

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# První demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Konec" -helptext "Ukončení aplikace" -armcommand {exit}

# vložení tlačítka do okna
pack .b

# finito 
TCL 17 - 1

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

Ve druhém demonstračním příkladu je ukázáno, jakým způsobem je možné na tlačítko vložit (vícebarevný) rastrový obrázek. Aby bylo zajištěno, že se ikona na obrázku zobrazí korektně v různých barevných schématech, musí se v obrázku použít buď alfa kanál (pokud ho daný grafický formát podporuje), nebo transparentní barva. Tato možnost je ukázána i v demonstračním příkladu, kdy je obrázek file_exit.gif vytvořen s transparentní barvou, která představuje pozadí ikony. Zadání transparentní barvy je možné v prakticky všech vyspělých grafických editorech i programech pro prohlížení a převody obrázků.

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Druhý demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -helptext "Ukončení aplikace" -command {exit} -image [image create photo -file file_exit.gif] -width 120

# vložení tlačítka do okna
pack .b

# finito 
TCL 17 - 2

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

2. Stavový řádek u libovolného okna

Nedílnou součástí GUI oken mnoha aplikací je i takzvaný stavový řádek. Ten v aplikacích plní současně více funkcí. Jak již název napovídá, zobrazuje se na stavovém řádku stav aplikace či alespoň nejdůležitější stavové informace (v textovém procesoru to může být počet stránek a aktuální pozice textového kurzoru). Kromě toho je na stavovém řádku možné zobrazovat i krátkou nápovědu, například při výběru položek z menu. Rohy stavového řádku současně slouží pro zvětšování a zmenšování okna či dialogu pomocí myši. V knihovně BWidgets je widget reprezentující stavový řádek dostupný pod jménem StatusBar. Tento widget se chová podobně jako další widgety, je ho tedy možné umístit prakticky kamkoli do okna (to je však značně netypické chování). Kromě toho se stavový řádek chová i jako kontejner, tj. na jeho plochu se mohou umisťovat další widgety – typicky to bývají texty (labels), skrolovací tlačítka, spin buttony nebo příkazová tlačítka. Použití stavového řádku je ukázáno na třetím demonstračním příkladu:

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Třetí demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření stavového řádku
StatusBar .s

# vložení widgetu do stavového řádku
.s add [Label .l -text "Stavový řádek" -helptext "Zde se nachází stavový řádek"]

# vložení tlačítka a stavového řádku do okna
pack .b
pack .s -fill both

# finito 
TCL 17 - 3

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

Jak je ze screenshotu třetího demonstračního příkladu patrné, není stavový řádek v okně umístěn tak, jak jsou uživatelé zvyklí, tj. na spodním okraji okna. Tento nedostatek je možné velmi jednoduše napravit tak, že správci rozvržení (pack) řekneme, že má daný widget udržovat při dolním okraji okna. Stavový řádek je tak opravdu vždy umístěn na spodním okraji, a to i v případě, že je velikost okna měněna. Vše názorně demonstruje čtvrtý příklad:

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Čtvrtý demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření stavového řádku
StatusBar .s

# vložení widgetu do stavového řádku
.s add [Label .l -text "Stavový řádek" -helptext "Zde se nachází stavový řádek"]

# vložení tlačítka a stavového řádku do okna
pack .b
pack .s -fill both -side bottom

# finito 

Poněkud podivnou vlastností knihovny BWidgets je skutečnost, že je možné vytvořit i několik stavových řádků zobrazených současně. Na tom není v případě ostatních widgetů nic divného, stavový řádek se však od dalších widgetů odlišuje v tom, že jeho rohy jsou aktivní a pomocí nich může uživatel měnit velikost okna – samozřejmě za předpokladu, že je změna velikosti okna povolena, což nemusí být pravda například u některých dialogových oken. Po spuštění pátého demonstračního příkladu se vytvoří celkem osm stavových řádků, každý přitom bude fungovat i při zvětšování či zmenšování svého rodičovského okna.

TCL 17 - 4

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

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Pátý demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření osmice stavových řádků
set names {.s1 .s2 .s3 .s4 .s5 .s6 .s7 .s8}
foreach name $names {
    StatusBar $name
}

# vložení tlačítka do okna
pack .b

# vložení stavových řádků do okna
foreach name $names {
    pack $name -fill both -side bottom
}

# finito 
TCL 17 - 5

Obrázek 5: Screenshot pátého demonstračního příkladu

3. Zobrazení stromové struktury

Velmi zajímavým a současně i důležitým widgetem poskytovaným knihovnou BWidgets je widget Tree, který slouží k zobrazení stromové struktury. Důležitost tohoto widgetu tkví v tom, že původní toolkit tk žádný widget s podobnou funkcionalitou neobsahoval, proto si programátoři aplikací museli tento widget tvořit sami, což je práce velmi zdlouhavá a složitá. Použití widgetu Tree je naopak jednoduché a poměrně přímočaré (jednodušší řešení jsem viděl pouze v prvních verzích knihovny VCL od Borlandu). Tento widget se totiž chová podobně jako kreslicí plátno (canvas), ale s tím rozdílem, že se do něj přímo nekreslí – vykreslování probíhá automaticky podle vložených dat. Kromě toho tento widget slouží i jako datový kontejner udržující si svá data organizovaná do stromové struktury.

Základním příkazem pro práci s datovou strukturou widgetu Tree je příkaz insert, pomocí nějž se data do stromu vkládají. Tento příkaz pro svou činnost potřebuje tři argumenty. V prvním argumentu je předáno místo, kam se bude nový datový prvek vkládat. Místo celočíselného indexu je možné použít speciální jméno end, které nahrazuje nejvyšší právě dostupný index. Ve druhém argumentu se předává jméno předka (rodiče), tj. uzlu, jehož poduzel je reprezentován právě vkládaným prvkem. Speciálním jménem je zde root, který označuje kořen stromu. Ve třetím argumentu se předává jméno nově vytvořeného uzlu (toto jméno se použije například při vkládání dalších poduzlů).

Použití widgetu Tree je ukázáno v šestém demonstračním příkladu.

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Šestý demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření stavového řádku
StatusBar .s

# vložení widgetu do stavového řádku
.s add [Label .l -text "Stavový řádek" -helptext "Zde se nachází stavový řádek"]

# vytvoření stromu
Tree .t
.t insert end root prvni -text "První"
.t insert end root druhy -text "Druhý"
.t insert end root treti -text "Třetí"
.t insert end root ctvrty -text "Čtvrtý"

foreach i {prvni druhy treti ctvrty} {
    foreach j {a b c d} {
        .t insert end $i $i$j -text Volba:$j
    }
}

# vytvoření nalšího uzlu stromu
.t insert end prvni pprvni -text "prvni"

# vložení tlačítka a stavového řádku do okna
pack .t -fill both -side top
pack .b
pack .s -fill both -side bottom

# finito 
TCL 17 - 6

Obrázek 6: Screenshot šestého demonstračního příkladu

4. Widget ComboBox

Podobně jako výše popsaný widget Tree nebyl ani widget ComboBox v původním toolkitu Tk obsažen. Jedná se však o velmi často používaný ovládací prvek, proto je jeho začlenění do knihovny BWidgets více než vhodné. Ve své podstatě se jedná o sloučení funkce editačního řádku s funkcí lisboxu. Kombo box je v okně zobrazen jako jeden řádek, do kterého je možné buď zapisovat text, nebo vybírat z přednastaveného seznamu textů. Kombo box může reagovat na různé události, typicky to bývá změna zapsaného textu či výběr některé položky. Základní použití tohoto widgetu je patrné ze sedmého demonstračního příkladu.

#!/usr/bin/wish

# Práce s knihovnou BWidget
# Sedmý demonstrační příklad

# načtení knihovny BWidget
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření stavového řádku
StatusBar .s

# vložení widgetu do stavového řádku
.s add [Label .l -text "Stavový řádek" -helptext "Zde se nachází stavový řádek"]

# vytvoření kombo boxu
ComboBox .cb -values {První Druhý Třetí Čtvrtý Pátý Šestý Sedmý Osmý}

# vložení tlačítka a stavového řádku do okna
pack .cb -fill both -side top
pack .b
pack .s -fill both -side bottom

# finito 
TCL 17 - 7

Obrázek 7: Screenshot sedmého demonstračního příkladu

5. Výběr barvy pomocí dialogu

Pro výběr barvy či barevné kombinace je v knihovně BWidgets připraven widget nazvaný SelectColor. Tento widget, jehož vzhled je systémově závislý, je možné zobrazit buď jako skutečné dialogové okno (volba -type dialog), nebo jako malé vyskakovací okénko (volba -type popup). Vyskakovací okénko sice na obrazovce zabírá méně místa, jeho použití je však problematičtější, zejména na systémech, kde se automaticky nepřesouvá fokus spolu s kurzorem myši. Oba typy widgetu pro výběr barvy vracejí kód barvy v textové podobě.

#!/usr/bin/wish

# Práce s knihovnou BWidgets
# Osmý demonstrační příklad

# načtení knihovny BWidgets
package require BWidget

# vytvoření tlačítka
Button .b -text "Ukončení aplikace" -helptext "Ukončení aplikace" -command {exit}

# vytvoření stavového řádku
StatusBar .s

# vložení widgetu do stavového řádku
.s add [Label .l -text "Stavový řádek" -helptext "Zde se nachází stavový řádek"]

# vytvoření dvou typů dialogů pro výběr barvy
SelectColor .sc1 -type dialog
SelectColor .sc2 -type popup

# vložení tlačítka a stavového řádku do okna
pack .b
pack .s -fill both -side bottom

# finito 
TCL 17 - 8

Obrázek 8: Screenshot prvního dialogu z osmého demonstračního příkladu

TCL 17 - 9

Obrázek 9: Screenshot druhého dialogu z osmého demonstračního příkladu

CS24_early

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

V dalším pokračování tohoto seriálu si ukážeme praktické příklady vytvořené s pomocí knihovny IWidgets.

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.