Tcl/Tk

Tk (z anglického  – „sada nástrojů“) je multiplatformní knihovna základních prvků grafického uživatelského rozhraní, kterou vyvinul John Ousterhout jako rozšíření interpretovaného programovacího jazyka Tcl.

Tk poskytuje sadu Tcl příkazů určených k vytváření ovládacích prvků a dalších komponent grafického uživatelského rozhraní a provádění různých akcí s nimi.

Knihovna Tk je distribuovaná jako otevřený software a byla přenesena na většinu implementací systémů Linux, OS X, Unix a Microsoft Windows. Pomocí speciálních knihoven může být knihovna Tk použita i v jiných programovacích jazycích, například v Perlu, Pythonu nebo Ruby. Většina těchto jazyků používá Tcl jako most pro Tk.

Od verze 8 mají widgety „nativní“ vzhled prostředí příslušného operačního systému, to znamená, že grafické prvky vypadají stejně jako prvky standardní pro tento OS. Od verze 8.5 je možné pro kreslení prvků použít engine s podporou motivů nazvaný Ttk. Existuje také několik rozšíření, které implementují Drag and drop mezi aplikacemi v Tk a externími aplikacemi, nepravoúhlá okna a podobně.

Komponenty jsou uspořádány v hierarchické struktuře. Z pohledu aplikace existuje hlavní nebo primární okno, ve kterém jsou vytvořena podřízená okna. Podřízená okna mohou zase působit jako rodiče ve vztahu k jiným oknům atd. Rozmístění komponentů řídí správce rozvržení nebo geometrie (), který určuje velikost komponent a jejich umístění na obrazovce.

Aplikace Tk, stejně jako většina aplikací v grafických prostředích, jsou programy řízené událostmi. Tk komponenty většinu událostí zpracovávají automaticky, což zjednodušuje vytváření aplikací.

Spuštění Tk skriptu obvykle začíná vytvářením komponent a jejich umístěním pomocí správce rozvržení, po němž skript přidružuje obslužné rutiny událostí se součástmi. Poté, co interpret dokončí analýzu příkazů odpovědných za inicializaci uživatelského rozhraní, přejde do smyčky událostí. Od tohoto okamžiku začne aplikace reagovat na akce uživatele.

Pro Tk existují další sady komponent, například BWidget, Tix nebo incr Widgets. Výhodou využití BWidget je, že není třeba kompilovat konkrétní platformu (jeho kód je „čisté“ Tcl).

Tcl, Tclsh, Tk a Wish 
Standardním interpretem Tcl je program tclsh; pro interpretaci skriptů v Tcl/Tk slouží příkaz wish (Windowing Shell). Na systémech standardu POSIX je wish interpret Tcl s vestavěným Tk; na jiných systémech se oba příkazy liší jen tím, že wish automaticky provede package require Tk, čímž zajistí načtení balíčku Tk z dynamické knihovny.

Tk skripty 
Tk skript je normální skript v jazyce Tcl; zavedením balíčku Tk však přibudou příkazy pro vytváření prvků a ovládání grafického uživatelského rozhraní neboli widgetů.

Zatímco ve „standardním“ Tcl se veškerá činnost provádí z hlavního programu (těla skriptu), v Tk se v něm pouze definují jednotlivé prvky rozhraní a jejich vazby na události. Vlastní komunikace s uživatelem se uskutečňuje po provedení posledního příkazu těla skriptu, kdy program vstoupí do smyčky událostí. Smyčka událostí je realizována příkazem tkwait, který se implicitně spouští na konci těla skriptu, může však být vyvolán i explicitně. Aplikace končí buď ukončením příkazu tkwait nebo explicitním provedením příkazu exit.

Widgety 
Tk poskytuje následující příkazy pro vytváření widgetů:

 toplevel – okno, ve kterém zobrazují ostatní prvky; první okno se jménem . se automaticky otevře při zavedení Tk
 canvas – plátno – plocha, na kterou lze rozmístit další prvky; používá se pro kreslení geometrických objektů nebo pokud je potřeba část okna scrollovat pomocí posuvníku
 panedwindow – okno s posuvnými částmi; umožňuje rozdělení okna na podokna, jejichž velikost lze měnit posouváním rámečků
 frame – rámeček (viditelný nebo neviditelný), kterým lze ohraničit prvky nebo jejich skupiny
 labelframe – rámeček přerušený nápisem
 label – nápis (etiketa)
 entry – okénko pro zadání jednoho řádku textu; text může být předvyplněn
 text – okno pro editaci víceřádkového textu (může být předvyplněn)
 button – obdélníkové tlačítko, na kterém může být nápis nebo obrázek; při kliknutí se zobrazí zamáčknutí tlačítka a provede se určitá akce
 checkbutton – zaškrtávací pole – malá čtvercová ploška, která při klikání mění stav mezi zapnuto a vypnuto
 radiobutton – přepínač – skupina kruhových plošek podobných zaškrtávacím polím, kliknutí na jednu z nich dojde k jejímu zapnutí a vypnutí všech ostatních ve skupině
 menu – klasická nabídka několika možností, kliknutím se provede určitá akce; může být víceúrovňové
 listbox – seznam několika možností uspořádaných podobně jako menu; kliknutím se však místo vyvolání akce vybere příslušná možnost
 combobox – kombinované pole – prvek, který se chová jako kombinace entry a listboxu
 menubutton – tlačítko, které se stisknutím rozvine na menu
 scrollbar – posuvník, pomocí kterého se lze posouvat na část plátna, textu nebo prvků, které se nemohly zobrazit pro nedostatek prostoru
 progressbar – posuvník ukazující průběh nějaké akce
 scale – posuvník sloužící k zadání hodnoty z určitého intervalu
 spinbox – entry pro zadání hodnoty doplněný šipkami, kterými lze přidávat nebo ubírat
 message – otevře nové okno, ve kterém je zobrazena zpráva
 notebook – přepínání několika dialogů na stejné ploše pomocí záložek (oslích uší)

Jména widgetů 
Prvním parametrem příkazů, které vytvářejí prvky grafického rozhraní, je jméno prvku. Protože toto jméno je strukturováno podobně jako úplné jméno souboru, bývá v angličtině označováno stejným slovem . Zatímco v úplném jménu souboru jsou jednotlivé části oddělovány znaky lomítko nebo zpětné lomítko, ve jménech prvků v Tcl/Tk se jednotlivé části cesty oddělují znaky tečka (.). Tečkou musí jméno také začínat; samotná tečka označuje výchozí prvek celé hierarchie, kterým je hlavní okno automaticky vytvořené zavedením balíčku Tk.

Například tlačítko b_yes umístěné v rámečku f_top v okně w2 by se mělo jmenovat .w2.f_top.b_yes. Protože Tcl/Tk nevyžaduje, aby jména prvků obsahovala i jména rámečků, lze použít i jméno .w2.b_yes. V tomto případě je však třeba explicitně zadat, že tlačítko se má zobrazit v rámečku .w2.f_top.

Správce oken 
V grafických aplikacích hraje důležitou roli komunikace se správcem oken (window managerem), což je aplikace, která se v systému stará o „dekoraci“ oken toplevel. Tuto komunikaci zajišťuje příkaz wm. Umožňuje vyžádat operace, které zajišťuje správce oken – např. nastavení velikosti okna, jeho minimalizaci, maximalizaci, ikonizaci, zjištění velikosti okna, a registrace událostí, které pocházejí od správce oken.

Lze také například předepsat zavření okna uživatelem:

 wm protocol .x WM_DELETE_WINDOW ExitWindowX

Ukázka programu v Tcl/Tk 
Následující program otevře dvě okna – hlavní o velikosti 320 x 200 pixelů obsahující nápis Nápis v hlavním okně s titulkem (v rámu okna) Hlavní okno a druhé s titulkem Druhé okno obsahující nápis Nápis v druhém okně, okolo kterého je ve všech směrech prostor 10 pixelů:

package require Tk

wm title . "Hlavní okno"
wm minsize . 320 200
label .l -text "Nápis v hlavním okně"
pack .l -padx 40 -pady 20

set w2 [toplevel .w2]
wm title $w2 "Druhé okno"
pack [label $w2.l -text "Nápis v druhém okně"] -padx 10 -pady 10

Příkaz wm title změní text v záhlaví okna a wm minsize předepíše jeho minimální velikost (šířka 320 pixelů a výška 200 pixelů); příkaz label připraví nápis, který se provedením příkazu pack zobrazí uvnitř okna.

Příkaz toplevel vytvoří druhé okno, jehož jméno, resp. cestu .w2 uložíme do proměnné w2. Dalším příkazem změníme text v jeho záhlaví. Poslední řádek ukazuje, jak je možné zkombinovat příkaz label, který vytvoří nápis, a příkaz pack, který zajistí jeho zobrazení.

Program nedefinuje žádný prostředek pro své ukončení. Ukončí se zavřením hlavního okna.

Vytváření widgetů 
Tk obsahuje řadu widgetů potřebných k vytvoření desktopových aplikací, jako jsou tlačítka, nabídky, texty, rámečky, štítky atd. Widgety jsou vytvořeny pomocí odpovídajících příkazů, kde prvním argumentem je cesta cesty widgetu. Tyto příkazy navíc také akceptují možnosti specifické pro widget, například:

 button .btn -text "Konec" -bg blue -fg white -command {exit}

Tlačítko "Konec" po svém stisknutí provede příkaz exit, tj. ukončení aplikace.

Správci rozvržení 
Aby byl grafický prvek vidět, je nutné použít správce rozvržení, který jej umístí do nadřízeného widgetu a zajistí jeho zobrazení. Tk poskytuje tři správce rozvržení, které se liší přístupem k umisťování widgetů do rodičovských oken:

 place – umisťuje widget na zadanou pozici v rámci nadřazeného okna
 pack – umisťuje widgety vedle sebe nebo pod sebou k okrajům nadřízeného widgetu
 grid – umisťuje widgety do obdélníkové mřížky

Nejoblíbenější (a nejjednodušší k použití) metodou rozmísťování prvků je pack. Pro zobrazení widgetu .btn v rodičovském okně .:

 pack .btn

Při určování, kde se mají jednotlivé prvky zobrazit, se správci rozvržení řídí jmény widgetů. Ze jména se snaží odvodit, jaké je jeho nadřazené okno. Toto přiřazení lze v rámci jednoho toplevel okna změnit použitím parametru -in.

Konfigurace 
Většinu parametrů, které jsou widgetu přiřazeny při jeho vytváření, lze měnit za běhu. Jméno, které widget dostane při svém vytvoření, lze použít jako příkaz (což je v Tcl často používaný přístup, například při implementaci tříd a objektů v Incr Tcl). Tento příkaz má dva „podpříkazy“ (které bývají nazývány metodami, protože podobně jsou metody implementovány v Incr Tcl): cget a configure. Metoda cget slouží k načtení hodnoty vybraného parametru widgetu, configure k její modifikaci nebo k načtení hodnot všech parametrů. Výše vytvořené tlačítko tak může být v průběhu zpracování změněno příkazem:

 .btn configure -text "Ukončit aplikaci"

Čtení hodnot widgetů 
Tk používá několik metod pro propojení widgetů s akcemi, které se podobají mechanismu signálu a slotů. Tyto mechanismy zahrnují:

 parametr -command, který přiřazuje k výchozí akci widgetu (například kliknutí na tlačítko) Tcl příkaz
 parametry -variable a -textvariable, které propojují widget s proměnnou; změna widgetu způsobí změnu hodnoty proměnné a naopak; na změnu stavu proměnné lze navázat akci příkazem trace add variable
 události popsané dále

Události 
Kromě přímého propojení proměnných nebo akcí s widgety umožňuje Tk také navázání akcí na události, které jsou zpravidla vysílány konkrétním widgetem. Událost obvykle popisuje text uzavřený mezi znaky < a >. Pomocí příkazu bind lze události přiřadit vlastní akci.

Události lze rozdělit na standardní a virtuální. Standardní události jsou události „pevně zabudované“ do knihovny Tk, které přímo souvisejí s událostmi přicházejícími z okna systému. Jedná se například o stisknutí klávesy na klávesnici (např. <Return>, <Control-C>), myši (např. <Double-Button-1>, <MouseEnter>, <MouseWheel>). Tyto události často poskytují speciálním způsobem další argumenty. Argumenty jsou označeny znakem % a odpovídajícím znakem v následném příkazu. Pokud např. použijeme příkaz

 bind .x <MouseWheel> "MouseScroll %D"

pak při použití kolečka myši nad widgetem .x (widget, který reaguje na kolečko myši, je jiný v systému Windows – kde jde o okno, které má focus – zatímco v X11 je to okno, ve kterém je ukazatel myši), bude vyvolaný příkaz MouseScroll, který jako argument dostane hodnotu delta udávající velikost posunutí.

Kromě toho existují také virtuální události, které může definovat program příkazem add event. Jména virtuálních událostí se zapisují mezi << ... >>. Widgety, které implementují textový editor, mohou například definovat událost <<Paste>>. Virtuální události je možné generovat příkazem event generate.

Tile 
Od října 2006 obsahuje Tcl/Tk balíček Tile, který dovoluje se více přiblížit přirozenému vzhledu operačního systému a dokonce i knihoven, např. Aqua, výchozímu vzhledu systému Windows XP, dokonce i TileQt

Příklady 
Minimalistický program pro čmárání myší v Tcl používá widget canvas, ke kterému jsou navázány akce kliknutí levým tlačítkem myši a pohyb se stisknutým levým tlačítkem myši. Vazby se definují v proceduře doodle:

proc doodle {w {color black}} {
    bind $w <1>         [list doodle'start %W %x %y $color]
    bind $w <B1-Motion> {doodle'move %W %x %y}
}

Kliknutím na levé tlačítko se vytvoří objekt čára, jehož počáteční a koncový bod jsou shodné:

proc doodle'start {w x y color} {
    set ::_id [$w create line $x $y $x $y -fill $color]
}

Při pohybu myši se stisknutým levým tlačítkem se čára prodlouží:

proc doodle'move {w x y} {
    $w coords $::_id [concat [$w coords $::_id] $x $y]
}

Hlavní program má kromě zavedení balíčku Tk pouze tři řádky:

package require Tk
pack [canvas .c -bg white] -fill both -expand 1
doodle .c
bind .c <Double-3> {%W delete all}

První příkaz vytvoří a zobrazí kreslicí plochu, druhý ji přiřadí výše definované akce. Poslední příkaz definuje, že dvojitým kliknutím pravým tlačítkem myši se kresba smaže.

Podpora Unicode 
Následující program zobrazí texty v češtině, řečtině, ruštině, hebrejštině, arabštině, čínštině a japonštině ve widgetu text:

package require Tk
bind all <Escape> {exit}

wm title . "Exemple Unicode"
pack [text .t -font {Arial 14}]
.t insert end "
Čeština:\t\t Příliš žluťoučký kůn úpěl ďábelské ódy
Řecká alfabeta:\t\t \u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA \u03AC\u03B3\u03BB\u03CE\u03C3\u03C3\u03B1
Azbuka:\t\t \u0420\u0443\u0441\u0441\u043A\u0438\u0439 \u044F\u0437\u044B\u043A
Hebrejské písmo:\t\t \u05DD\u05D9\u05DC\u05E9\u05D5\u05E8\u05D9\u05DC\u05D9\u05D0\u05E8\u05E9\u05D9
Arabské písmo:\t\t \uFE94\uFEF4\uFE91\uFEAE\uFECC\uFEDF\uFE8D\uFE94\uFEE4\uFEE0\uFEDC\uFEDF\uFE8D
Tradiční čínština:\t\t \u4E2D\u570B\u7684\u6F22\u5B57
Japonské písmo:\t\t \u65E5\u672C\u8A9E\u306E\u3072\u3089\u304C\u306A,\u6F22\u5B57\u3068\u30AB\u30BF\u30AB\u30CA
"

Digitální hodiny 
Digitální hodiny vytvořené na 6 řádcích kódu:

package require Tk

proc every {t script} {
    eval $script
    after $t [list every $t $script]
}
pack [label .hodiny -textvariable time -font {Lucida 18}]
every 1000 {set ::time [clock format [clock seconds] -format %H:%M:%S]}

Odkazy

Reference

Související články 
 Tcl
 Tk (framework)
 Expect
 Tkinter – Tk vazby pro Python
 Itk
 Itcl
 wish (Windowing Shell)

Externí odkazy 
 Tcl Developer Xchange: Oficiální web Tcl a Tk
 Wiki pro uživatele Tcl
 wiki.tcl.tk/486 – Beginning Tk na wiki tcl tk
 Tk 8.6 Manuál
 ActiveTcl 8.6 Dokumentace
 Tk docs: moderní Tk tutoriál pro Tcl, Ruby, Perl a Python
 Tcl-Tk v archivu webu dmoz 
 Tcl/Tk 8.6.2 Documentation
 LTK Common Lisp vazby pro Tk

Rodina jazyků Tcl
Widget toolkity
Rozhraní pro programování aplikací
Svobodný software