Programovací jazyk TCL (12)

4. 10. 2005
Doba čtení: 12 minut

Sdílet

V dnešním pokračování seriálu o programovacím jazyku Tcl a k němu příslušejícím toolkitu Tk se budeme zabývat tvorbou menu, které tvoří nedílnou součást většiny aplikací využívajících grafické uživatelské rozhraní (GUI).

Obsah

1. Nabídky (menu) v knihovně Tk
2. Roletové menu (pull down)
3. Horké klíče v menu
4. Úprava barvy položek menu
5. Použití bitmap a pixmap v položkách menu
6. Vynořující se menu (pop up)
7. Menu jako samostatné okno
8. Klávesové akcelerátory
9. Obsah dalšího pokračování tohoto seriálu

1. Nabídky (menu) v knihovně Tk

Rozbalovací nabídky (menu) patří mezi nedílnou součást každého složitějšího programu s grafickým uživatelským rozhraním. Systém menu nabízí uživateli GUI aplikace jednu nebo více nabídek, které je možné vybrat, nastavit nebo přepnout. Bývá dobrým zvykem, že menu ve své struktuře obsahuje všechny příkazy a parametry provozované aplikace (ne všechny příkazy musí být samozřejmě po celou dobu běhu aplikace dostupné). Dnes se bohužel i u profesionálních aplikací stává, že je toto pravidlo často porušováno a některé příkazy zůstávají skryty pouze v dialozích nebo v konfiguračních souborech. Mezi velké výhody menu patří to, že si uživatel nemusí pamatovat způsob zadávání parametrů (například pomocí klíčových slov nebo formulářů) – vše je snadno dosažitelné právě ze struktury menu. Také pro programátory je tvorba menu mnohdy jednodušší než návrh dialogových boxů. Na druhou stranu může systém menu zdržovat v práci zkušenější uživatele, z toho důvodu je vhodné menu spojit s dalšími prvky grafického uživatelského rozhraní (tlačítky, výběrovými boxy a především horkými klávesami).

Poznámka: v dalším textu se budu zabývat výhradně aplikacemi s grafickým uživatelským rozhraním (GUI). Menu a další ovládací prvky je však možné použít i v textovém uživatelském rozhraní (tj. při ovládání celé obrazovky terminálu, nikoli při práci s příkazovým řádkem). Příkladem textově orientovaných aplikací využívajících menu jsou například všechny aplikace naprogramované pomocí knihovny Turbo Vision firmy Borland a dále takové produkty, jako jsou Midnight Commander, Links, WE, Turbo Pascal, Turbo C++, Turbo Basic, Norton Commander, DOS Navigator, Volkov Commander, dBase III, FoxPro, Microsoft Word, Lotus 1–2–3 a velké množství dalších aplikací dostupných pro systémy Linux a DOS.

V některých systémech GUI je menu složeno z jednodušších objektů (widgetů) – z toho také vyplývá, že se zde menu chová jako kontejner schopný pojmout další widgety. Existují však i GUI systémy, kde je menu považováno za jeden dynamicky se měnící widget, který je rozdělen do jednotlivých objektů – položek menu (to má výhody v tom, že se pro menu alokuje méně systémových zdrojů). Nejvíce příkazů je možné z menu vyvolat pomocí zamačkávacích tlačítek (push-button). S využitím tlačítek se přímo spouští nějaká naprogramovaná akce. Dále je možné v menu používat zaškrtávací/vý­běrová tlačítka (check-button) a přepínací tlačítka (radio-button). V případě, že je menu hierarchicky strukturováno, je k dispozici ještě tlačítko, které slouží k přechodu na nižší úroveň. Některé programy, například vývojová prostředí firmy Borland, používají pouze jednoúrovňové menu, v dalších programech jsou menu mnohdy složitě strukturovaná (GIMP apod.). V průběhu vývoje grafických uživatelských rozhraní se ustálily čtyři typy menu:

  1. roletové menu (pull down)
  2. vynořující se menu (pop up) – také kontextové menu
  3. výběrové menu (option)
  4. kaskádové menu (cascading)

V dalších kapitolách si jednotlivé typy menu popíšeme spolu s ukázkou podpory v Tcl/Tk.

2. Roletové menu (pull down)

Roletové menu (pull down) patří mezi základní typy menu, a je proto dostupné prakticky ze všech aplikací využívajících grafické uživatelské rozhraní. Z celého menu je bez jeho aktivace viditelná pouze nejvyšší úroveň, která se nachází na takzvané liště. Standardně bývá lišta umístěna v horní části okna aplikace, i když samozřejmě existují výjimky, například rozhraní Exploreru v systémech Microsoft Windows. Mezi výhody tohoto typu menu patří skutečnost, že uživatel vždy vidí nejvyšší úroveň příkazů, a nemusí tedy složitě pátrat nebo slepě zkoušet, ve kterém místě se menu aktivuje (to je případ mnohých multimediálních přehrávačů, u kterých autoři preferují „originalitu“ před použitelností). Další výhoda roletového menu spočívá ve stálé viditelnosti klíčů (horkých kláves) pro příkazy na základní úrovni (pokud tedy není viditelnost klíčů zakázána, jak to nelogicky a snad naschvál dělají ve standardní instalaci nové systémy Microsoft Windows – je však pravda, že podobným způsobem zlobily i DOSové výrobky této firmy). Některé aplikace z roletového menu používají pouze lištu, na které se položky dynamicky mění; tento způsob však ztratil svůj půvab ve chvíli, kdy množství funkcí dostupných z menu rapidně vzrostlo. Příkladem aplikace využívající pouze lištu menu je například Lotus 1–2–3 nebo z ještě starších aplikací textový editor Cheops Writer dostupný pro osmibitová Atari. Opakem menu zobrazovaného pouze na liště je takzvané screen menu používané například u AutoCADu – to se později jako velká „novinka“ objevilo i u Microsoft Office.

Tcl/Tk se roletové menu vytváří velmi snadno, jak je ostatně patrné z prvního demonstračního příkladu:

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# první demonstrační příklad

. configure -menu [menu .m -tearoff 0 -type menubar]
.m add cascade -menu [menu .m.file -tearoff 0] -label "File"
.m add cascade -menu [menu .m.edit -tearoff 0] -label "Edit"
.m add cascade -menu [menu .m.help -tearoff 0] -label "Help"

.m.file add command -label "New"
.m.file add command -label "Open"
.m.file add command -label "Save"
.m.file add separator
.m.file add command -label "Exit" -command exit

.m.edit add command -label "Undo"
.m.edit add separator
.m.edit add command -label "Cut"
.m.edit add command -label "Copy"
.m.edit add command -label "Paste"
.m.edit add command -label "Delete"
.m.edit add separator
.m.edit add command -label "Select All"

.m.help add command -label "About" 
TCL 12 - 1

Obrázek 1: Screenshot prvního demonstračního příkladu s menu na Windows XP

TCL 12 - 2

Obrázek 2: Screenshot prvního demonstračního příkladu s menu na X Window systému

Menu je nejprve vytvořeno a je mu přiřazeno jméno, v našem případě .m. Poté se do menu vloží položky na nejvyšší úrovni a posléze se do každé této položky, která je jednoznačně pojmenovaná, vloží jednotlivé příkazy. Ještě si všimněte toho, že mezi položky/příkazy je možné vložit takzvaný separátor, který má ve většině GUI systémů tvar horizontální úsečky. Ke každé položce menu je možné přiřadit jeden příkaz, který se provede při výběru položky.

3. Horké klíče v menu

Jednotlivé položky menu je možné modifikovat pomocí několika příkazů. Pravděpodobně nejpoužívanější modifikací je přiřazení horkých klíčů jednotlivým položkám – to se provádí pomocí volby -underline, za níž následuje index znaku, který má být podtržen. První znak má index rovný nule. V některých GUI systémech je horký klíč specifikován přímo v textu jednotlivých položek pomocí speciálního znaku (například ampersandu). Tuto funkcionalitu je do Tcl/Tk také možné doplnit pomocí jednoduché procedury, která bude mít jako své parametry identifikátor menu a řetězec se speciálním znakem.

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# druhý demonstrační příklad

. configure -menu [menu .m -tearoff 0]
.m add cascade -menu [menu .m.file -tearoff 0] -label "File" -underline 0
.m add cascade -menu [menu .m.edit -tearoff 0] -label "Edit" -underline 0
.m add cascade -menu [menu .m.help -tearoff 0] -label "Help" -underline 0

.m.file add command -label "New"  -underline 0
.m.file add command -label "Open" -underline 0
.m.file add command -label "Save" -underline 0
.m.file add separator
.m.file add command -label "Exit" -underline 1 -command exit

.m.edit add command -label "Undo" -underline 0
.m.edit add separator
.m.edit add command -label "Cut" -underline 2
.m.edit add command -label "Copy" -underline 0
.m.edit add command -label "Paste" -underline 0
.m.edit add command -label "Delete" -underline 2
.m.edit add separator
.m.edit add command -label "Select All" -underline 7

.m.help add command -label "About" -underline 0 
TCL 12 - 3

Obrázek 3: Screenshot druhého demonstračního příkladu s menu na Windows XP

TCL 12 - 4

Obrázek 4: Screenshot druhého demonstračního příkladu s menu na X Window systému

4. Úprava barvy položek menu

Podobně jako v minule popsaném widgetu text je i u položek menu možné měnit barvy textu či barvy pozadí. Na dalším demonstračním příkladu je ukázáno, jakým způsobem je možné vytvořit různobarevné položky. Položky však nejsou vytvářeny otrocky jedna po druhé, ale je použit seznam nazvaný colors, kterým se prochází pomocí „seznamové“ smyčky foreach:

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# třetí demonstrační příklad

. configure -menu [menu .m -tearoff 0]
.m add cascade -menu [menu .m.file -tearoff 0]   -label "File"   -underline 0
.m add cascade -menu [menu .m.edit -tearoff 0]   -label "Edit"   -underline 0
.m add cascade -menu [menu .m.colors -tearoff 0] -label "Colors" -underline 0
.m add cascade -menu [menu .m.help -tearoff 0]   -label "Help"   -underline 0

.m.file add command -label "New"  -underline 0
.m.file add command -label "Open" -underline 0
.m.file add command -label "Save" -underline 0
.m.file add separator
.m.file add command -label "Exit" -underline 1 -command exit

.m.edit add command -label "Undo" -underline 0
.m.edit add separator
.m.edit add command -label "Cut" -underline 2
.m.edit add command -label "Copy" -underline 0
.m.edit add command -label "Paste" -underline 0
.m.edit add command -label "Delete" -underline 2
.m.edit add separator
.m.edit add command -label "Select All" -underline 7

set colors {white yellow orange red magenta blue cyan green}
foreach c $colors {
    .m.colors add command -label $c -background $c
}

.m.help add command -label "About" -underline 0 
TCL 12 - 5

Obrázek 5: Screenshot třetího demonstračního příkladu s menu na Windows XP

TCL 12 - 6

Obrázek 6: Screenshot třetího demonstračního příkladu s menu na X Window systému

5. Použití bitmap a pixmap v položkách menu

Spolu se zvyšujícími se kapacitami operačních pamětí počítačů se s touto pamětí začíná značně plýtvat. Jedním z důkazů je i použití bitmap a pixmap v položkách menu. Tyto rastrové obrázky přiřazené přímo k jednotlivým položkám menu vlastně nahrazují ikony používané v oknech a na toolbarech. Obrázky je možné vytvořit programově, častěji se však nahrávají z externích souborů. V následujícím demonstračním příkladu je ukázáno, jakým způsobem je možné rastrové obrázky nahrát ze souboru:

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# čtvrtý demonstrační příklad

. configure -menu [menu .m -tearoff 0]
.m add cascade -menu [menu .m.file -tearoff 0]   -label "File"   -underline 0
.m add cascade -menu [menu .m.edit -tearoff 0]   -label "Edit"   -underline 0
.m add cascade -menu [menu .m.colors -tearoff 0] -label "Colors" -underline 0
.m add cascade -menu [menu .m.help -tearoff 0]   -label "Help"   -underline 0

.m.file add command -label "New"  -underline 0 -image [image create photo -file file_new.gif] -compound left
.m.file add command -label "Open" -underline 0 -image [image create photo -file file_open.gif] -compound left
.m.file add command -label "Save" -underline 0 -image [image create photo -file file_save.gif] -compound left
.m.file add separator
.m.file add command -label "Exit" -underline 1 -command exit -image [image create photo -file file_exit.gif] -compound left

.m.edit add command -label "Undo" -underline 0
.m.edit add separator
.m.edit add command -label "Cut" -underline 2 -image [image create photo -file edit_cut.gif] -compound left
.m.edit add command -label "Copy" -underline 0 -image [image create photo -file edit_copy.gif] -compound left
.m.edit add command -label "Paste" -underline 0 -image [image create photo -file edit_paste.gif] -compound left
.m.edit add command -label "Delete" -underline 2 -image [image create photo -file file_exit.gif] -compound left
.m.edit add separator
.m.edit add command -label "Select All" -underline 7

set colors {white yellow orange red magenta blue cyan green}
foreach c $colors {
    .m.colors add command -label $c -background $c
}

.m.help add command -label "About" -underline 0 -image [image create photo -file help.gif] -compound left 
TCL 12 - 7

Obrázek 7: Screenshot čtvrtého demonstračního příkladu s menu na Windows XP

TCL 12 - 8

Obrázek 8: Screenshot čtvrtého demonstračního příkladu s menu na X Window systému

6. Vynořující se menu (pop up)

Vynořující se menu (pop up), které se někdy nazývá také kontextové menu, je charakteristické tím, že se může zobrazit (vynořit) v kterémkoli místě okna aplikace (netypický zástupce vynořujícího se menu byl použit například ve známém textovém editoru T602, zde se však menu vynořovalo vždy na stejném místě). Často se podle místa také mění příkazy dostupné z menu. Toto menu je výhodné v tom, že spoří místo v okně a navíc se při ovládání aplikace myší nemusí při vyvolání menu dojíždět až na lištu, jak tomu je v případě roletových menu. Rovněž dynamická (kontextová) změna příkazů v menu je velmi výhodná, protože uživatel dostane k dispozici pouze ty příkazy, které mají pro vybraný objekt smysl. Jediná nevýhoda tohoto typu menu spočívá v tom, že uživatel musí o existenci menu předem vědět nebo experimentovat. V Tcl/Tk se s pop up menu pracuje velmi jednoduše, nesmíme ovšem zapomenout na navázání nějaké události k tomuto menu. Typicky se pro vyvolání tohoto menu používá pravé tlačítko myši, jak je ostatně naznačeno v pátém demonstračním příkladu (připomínám, že tlačítka myši jsou v Tcl/Tk číslována trošku zmateně, takže pravé tlačítko má číslo 3). Při umístění menu pomocí příkazu tk_popup je možné použít speciální proměnné X a Y, které udávají absolutní pozici kurzoru myši (proměnné x a y zase udávají pozici relativní vůči počátku okna).

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# pátý demonstrační příklad

set m [menu .popupMenu -tearoff 0]
$m add command -label "Cut"
$m add command -label "Copy"
$m add command -label "Paste"
$m add command -label "Delete"
$m add separator
$m add command -label "Exit" -command exit

bind . <3> { tk_popup .popupMenu %X %Y } 
TCL 12 - 9

Obrázek 9: Screenshot pátého demonstračního příkladu s menu na Windows XP

TCL 12 - 10

Obrázek 10: Screenshot pátého demonstračního příkladu s menu na X Window systému

7. Menu jako samostatné okno

Možná jste si v předchozích demonstračních příkladech všimli, že při vytváření menu se používá volba -tearoff 0. Pokud tato volba není uvedena nebo je explicitně zapsáno -tearoff 1, stane se dané menu „odtrhovací“, tj. výběrem čárkované čáry zobrazené ve vrchní části menu se menu odtrhne od svého okna a vytvoří okno samostatné. To je velmi výhodné, protože velkou část grafického uživatelského rozhraní je možné nahradit právě těmito typy menu (je škoda, že ještě nikdo nevytvořil kombinaci menu, toolboxů a samostatných oken) a podle preferencí uživatele mohou být příkazy buď stále viditelné, nebo skryté v menu. Ze známých aplikací využívá tuto možnost například gvim (pouze na některých GUI systémech) a rastrový grafický editor GIMP.

#!/usr/bin/wish

# Práce s menu pomocí toolkitu Tk
# šestý demonstrační příklad

menu .popup
.popup add command -label "Cut"
.popup add command -label "Copy"
.popup add command -label "Paste"
.popup add command -label "Delete"
.popup add separator
.popup add command -label "Exit" -command exit

bind . <3> { tk_popup .popup %X %Y } 
TCL 12 - 11

Obrázek 11: Screenshot šestého demonstračního příkladu s menu na Windows XP

TCL 12 - 12

Obrázek 12: Screenshot šestého demonstračního příkladu s menu na X Window systému

8. Klávesové akcelerátory

Nastavení klávesových akcelerátorů (což je další typ horkých klíčů) se musí provést ve dvou krocích. Nejprve je nutné akcelerátor specifikovat u každé položky menu pomocí volby -accelerator, například:

.m.file add command -label "New" -underline 0 -accelerator Ctrl+N 

To však není vše, protože je ještě nutné akcelerátor na položku (resp. na nějaký příkaz) navázat. K tomu se používá nám již známý příkaz bind. Pro označení modifikátorů kláves se používají prefixy Control- a Meta-. Také si všimněte, že se rozlišují velikosti písmen stisknutých kláves, takže je rozdíl mezi zápisem Control-x a Control-X (druhá možnost nemusí na některých systémech vůbec fungovat).

ict ve školství 24

bind . <Control-a> {SelectAll}
bind . <Control-x> {Cut}
bind . <Control-c> {Copy}
bind . <Control-v> {Paste} 

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

V následujícím pokračování seriálu o Tcl/Tk bude probrána tvorba dialogových oken. Rovněž si popíšeme zbývající typ menu, který knihovna Tk nabízí.

Autor článku

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