Obsah
1. Práce s textem pomocí widgetu text
2. Použití tagů ve widgetu text
3. Rozměry widgetu text a tabelační zarážky
4. Další vlastnosti vkládaných řetězců
5. Reakce na události – hyperlinky
6. Další widgety vložené ve widgetu text
7. Obrázky ve widgetu text
8. Dodatek k předchozí části
9. Obsah dalšího pokračování tohoto seriálu
1. Práce s textem pomocí widgetu text
Největší část tohoto pokračování seriálu o jazyku Tcl a toolkitu/knihovně Tk nám zabere popis widgetu text, který je velmi často použit jako pevný základ pro vytváření různých prohlížečů strukturovaných či formátovaných textů s obrázky. Základní informace o widgetu text jsme si pověděli již v předchozí části tohoto seriálu. Připomeňme si pouze, že pomocí tohoto velmi flexibilního widgetu je možné zobrazovat a editovat jak jednoduchý text (textový řetězec), tak i text různými způsoby zformátovaný. Do textu lze také vkládat další objekty, zejména bitmapy a pixmapy. Pro připomenutí si také zopakujeme příklad, který demonstroval základní použití widgetu text – tento příklad budeme v dalších kapitolách postupně upravovat a rozšiřovat. V tomto příkladu se widget text (pojmenovaný pro jednoduchost .text) nachází jako jediná komponenta v okně aplikace. Do tohoto widgetu jsou pomocí procedury insert vloženy dva řetězce, každý je zobrazen na samostatném řádku díky znaku \n
. Zdrojový kód prvního demonstračního příkladu vypadá následovně:
#!/usr/bin/wish
# Použití widgetu text
# První demonstrační příklad
# vytvoření widgetu text
text .text
# vložení widgetu text do jediného okna aplikace
pack .text
# práce s widgetem
.text insert end "Hello\n"
.text insert end "world!\n"
Poznámka: screenshoty všech demonstračních příkladů jsou vytvořeny na Windows XP a live distribuci Linuxu Danix se spuštěným systémem X Window s KDE. Kromě změn okrajů okna, které má na starosti správce oken (a aplikaci prakticky nezajímají), si všimněte také některých odlišností ve způsobu renderování textů.
Obrázek 1: Screenshot prvního demonstračního příkladu s widgetem text na Windows XP
Obrázek 2: Screenshot prvního demonstračního příkladu s widgetem text na X Window systému
2. Použití tagů ve widgetu text
Pokud potřebujeme u textových řetězců vkládaných do widgetu text měnit jejich vlastnosti, například barvu či typ a velikost písma, můžeme použít již minule popsané tagy. Pomocí tagů se, zjednodušeně řečeno, pojmenuje určitá vlastnost nebo skupina vlastností a při vkládání řetězců do widgetu text pomocí příkazu insert se tyto vlastnosti řetězcům přiřadí. Velká výhoda tagů spočívá v tom, že jim přidružené vlastnosti je možné za běhu aplikace měnit, přičemž se změny ihned projeví na vizuálním vzhledu textu. Ukažme si druhý příklad, kde se pomocí tagů vypíše několik řádků textu, každý řádek je přitom vykreslen jinou barvou (při vytváření tagů se za slovo configure vkládá název tagu, nenechte se tedy zmást zdánlivě dvojím zápisem barvy). V příkladu si také všimněte, že se celému widgetu text pomocí zápisu -background black přiřadila černá barva pozadí, aby bylo barevné písmo na obrazovce lépe čitelné.
#!/usr/bin/wish
# Použití widgetu text
# Druhý demonstrační příklad
# vytvoření widgetu text (a změna barvy pozadí)
text .text -background black
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure red -foreground red
.text tag configure green -foreground green
.text tag configure blue -foreground blue
.text tag configure magenta -foreground magenta
.text tag configure cyan -foreground cyan
.text tag configure yellow -foreground yellow
.text tag configure brown -foreground brown
.text tag configure pink -foreground pink
.text tag configure white -foreground white
# práce s widgetem
.text insert end "Red\n" red
.text insert end "Magenta\n" magenta
.text insert end "Blue\n" blue
.text insert end "Cyan\n" cyan
.text insert end "Green\n" green
.text insert end "Yellow\n" yellow
.text insert end "Brown\n" brown
.text insert end "Pink\n" pink
.text insert end "White\n" white
Obrázek 3: Screenshot druhého demonstračního příkladu s widgetem text na Windows XP
Obrázek 4: Screenshot druhého demonstračního příkladu s widgetem text na X Window systému
Pravděpodobně již tušíte, že druhý příklad nebyl napsán tím nejlepším způsobem, protože se v něm opakují stále stejné příkazy. Abychom program přepsali z „C-čkovského“ stylu do stylu preferovaného v dynamických programovacích jazycích, můžeme použít flexibilní datový typ seznam, ve kterém budou uloženy názvy barev – tento seznam se v našem případě bude výstižně jmenovat barvy. Celý program se potom zkrátí, protože seznamem lze iterovat pomocí smyčky typu foreach. Ve skutečnosti by bylo možné vytvářet tagy spolu s vkládáním řetězců do widgetu text, a tak v programu použít pouze jednu smyčku (tím by se seznam ani nemusel pojmenovávat, protože by byl zapsán v hlavičce smyčky):
#!/usr/bin/wish
# Použití widgetu text
# Třetí demonstrační příklad
# vytvoření widgetu text
text .text -background black
# vložení widgetu text do jediného okna aplikace
pack .text
set barvy {red magenta blue cyan green yellow brown pink white}
# nastavení tagů v cyklu
foreach barva $barvy {
.text tag configure $barva -foreground $barva
}
# práce s widgetem
foreach tag $barvy {
.text insert end $tag $tag
.text insert end "\n"
}
Obrázek 5: Screenshot třetího demonstračního příkladu s widgetem text na Windows XP
Obrázek 6: Screenshot třetího demonstračního příkladu s widgetem text na X Window systému
Kromě barev vykreslovaných řetězců je možné měnit i typ písma, což je ukázáno na dalším demonstračním příkladu. Zde si můžete všimnout, že vlastnosti underline (podtržení) a overstrike (přeškrtnutí) se povolují a zakazují přiřazením logické hodnoty true/false resp. 1/0. Na první pohled korektní zápis .text tag configure podtrzene -underline je tedy ve skutečnosti chybný.
#!/usr/bin/wish
# Použití widgetu text
# Čtvrtý demonstrační příklad
# vytvoření widgetu text
text .text -background DarkBlue -width 40 -height 24
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure red -foreground red -underline 1
.text tag configure magenta -foreground magenta -overstrike 1
.text tag configure green -foreground green -font "Helvetica 50"
.text tag configure blue -foreground blue -underline 0
.text tag configure cyan -foreground cyan -underline 1 -font "Courier 20"
# práce s widgetem
.text insert end "Red\n" red
.text insert end "Magenta\n" magenta
.text insert end "Blue\n" blue
.text insert end "Cyan\n" cyan
.text insert end "Green\n" green
Obrázek 7: Screenshot čtvrtého demonstračního příkladu s widgetem text na Windows XP
Obrázek 8: Screenshot čtvrtého demonstračního příkladu s widgetem text na X Window systému (část textu je vybrána)
(Ještě bych rád připomenul, že u všech výše popsaných příkladů je zachována editovatelnost textu, nejedná se tedy o neživou část GUI, ale část aktivně komunikující s uživatelem.)
3. Rozměry widgetu text a tabelační zarážky
Rozměry widgetu text se specifikují již při jeho vytváření pomocí voleb -width xx a -height yy, všechny rozměry se přitom neudávají v pixelech ani jiných jednotkách, ale v počtu normalizovaných znaků. Výpočet skutečné výšky a šířky widgetu provede Tk automaticky pomocí informací získaných z použitého fontu. Kromě rozměrů widgetu je možné specifikovat i pozice tabelačních zarážek. Ty se zadávají pomocí volby -tabs seznam. Seznam obsahuje pozice tabelačních zarážek; tyto pozice jsou chápány jako vzdálenosti zarážek od levého okraje widgetu. Pokud je za číslem udávajícím vzdálenost zapsán znak „c“, znamená to, že se vzdálenost bude počítat v šířkách normalizovaných znaků. Pozor na to, že použitý font může obsahovat (a většinou obsahuje) proporcionální znaky a v některých případech nemusí výpočet šířky normalizovaných znaků proběhnout korektně – to je případ zejména různých sharewarových TrueType fontů, které někdy mají špatně vyplněnou tabulku s metrikami (tyto fonty se však nebudou chovat korektně ani v dalších aplikacích). Pokud se v seznamu s tabelačními zarážkami uvede jedno ze slov left, right, center nebo numeric, značí to způsob zarovnání textu vůči zarážce – zarovnání doleva, doprava, na střed a na desetinnou tečku/čárku. Tato funkce se chová stejně jako v textových procesorech.
V dalším demonstračním příkladu je vytvořen widget text, který bude mít rozměry 40×24 normoznaků. Přitom jsou nastaveny dvě tabelační zarážky – na první se text zarovnává doprava, na druhé doleva (což je jinak implicitní volba). Všimněte si, že znak tabelátoru se do řetězce zadává stejným způsobem jako v mnoha dalších programovacích jazycích (C, C++, Java, Perl…). Některé řádky textu jsou zobrazeny jinou barvou a první řádek je podtržen. Toho bylo dosaženo vytvořením tagů nadpis a suma.
#!/usr/bin/wish
# Použití widgetu text
# Pátý demonstrační příklad
# vytvoření widgetu text
text .text -background white -width 40 -height 24 -tabs {3c right 4c left}
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure nadpis -foreground red -underline 1
.text tag configure suma -foreground blue
# práce s widgetem
.text insert end "Mesic\tObrat\n" nadpis
.text insert end "leden\t100\n"
.text insert end "unor\t200\n"
.text insert end "brezen\t0\n"
.text insert end "duben\t1000\n"
.text insert end "kveten\t100\n"
.text insert end "cerven\t200\n"
.text insert end "cervenec\t0\tdovolene\n"
.text insert end "srpen\t1000\n"
.text insert end "zari\t100\n"
.text insert end "rijen\t200\n"
.text insert end "listopad\t0\n"
.text insert end "prosinec\t1100\tvanoce\n\n"
.text insert end "suma\t3900" suma
Obrázek 9: Screenshot pátého demonstračního příkladu s widgetem text na Windows XP
Obrázek 10: Screenshot pátého demonstračního příkladu s widgetem text na X Window systému
4. Další vlastnosti vkládaných řetězců
Pomocí tagů je možné nastavit i další vlastnosti textových řetězců, které se vkládají do widgetu text. Pro mnoho aplikací je důležité nastavení zarovnávání textů. To je možné obstarat buď pomocí výše zmíněných tabelačních zarážek (což je mnohdy zbytečně komplikované), nebo pomocí vlastnosti -justify. Této vlastnosti lze přiřadit více hodnot – left, right a center (prozatím není k dispozici možnost zarovnat text do bloku). Dále je možné zvýraznit okraj okolo textu (funguje korektně i pro víceřádkový text). Tento okraj může být opticky buď vysunutý, nebo zasunutý (raised, sunken). Horní a dolní indexy se tvoří pomocí změny hodnoty vlastnosti -offset, pomocí které je možné text vertikálně posunout vůči textové osnově (kromě toho je vhodné text zmenšit o jeden až dva body). Nastavení všech těchto vlastností je patrné z dalšího demonstračního příkladu, který rozšiřuje příklad předchozí:
#!/usr/bin/wish
# Použití widgetu text
# Šestý demonstrační příklad
# vytvoření widgetu text
text .text -background White -width 40 -height 24
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure red -foreground red -underline 1
.text tag configure magenta -foreground magenta -overstrike 1
.text tag configure green -foreground green -font "Helvetica 50"
.text tag configure blue -foreground blue -underline 0
.text tag configure cyan -foreground cyan -underline 1 -font "Courier 20"
.text tag configure raised -relief raised -borderwidth 2
.text tag configure sunken -relief sunken -borderwidth 2
.text tag configure center -justify center
.text tag configure left -justify left
.text tag configure right -justify right
.text tag configure sup -offset 3p
.text tag configure sub -offset -3p
# práce s widgetem
.text insert end "Red\n" red
.text insert end "Magenta\n" magenta
.text insert end "Blue\n" blue
.text insert end "Cyan\n" cyan
.text insert end "Green\n" green
.text insert end "Raised box\n" raised
.text insert end "\n"
.text insert end "Sunken box\n" sunken
.text insert end "\n"
.text insert end "Centered text\n" center
.text insert end "Left justificiation\n" left
.text insert end "Right justificiation\n" right
.text insert end "H"
.text insert end "2" sub
.text insert end "O\n"
.text insert end "E=mc"
.text insert end "2" sup
Obrázek 11: Screenshot šestého demonstračního příkladu s widgetem text na Windows XP
Obrázek 12: Screenshot šestého demonstračního příkladu s widgetem text na X Window systému
5. Reakce na události – hyperlinky
Každý objekt vkládaný do widgetu text (ať se jedná o textový řetězec či jiný widget) může reagovat na různé události. Vazba objektu na události se vytvoří pomocí příkazu bind při vytváření tagu, který je objektům přiřazen. Mezi podporované události patří stisk či puštění libovolného tlačítka myši, posun kurzoru myši, přesun kurzoru myši nad objekt či opuštění hranic objektu atd. V sedmém demonstračním příkazu je ukázáno, jak lze nakonfigurovat tag pojmenovaný colorOnEnter pomocí vazeb na dvě události. První událost nastane v případě, že je nad hranice objektu přesunut kurzor myši, druhá událost nastane ve chvíli opuštění hranic objektu kurzorem myši. Tyto události se nazývají Any-Enter a Any-Leave. Při vytváření hypertextových odkazů se mohou použít známé události ButtonPress a ButtonRelease – viz předchozí část tohoto seriálu s popisem jednoduchého vektorového grafického editoru.
#!/usr/bin/wish
# Použití widgetu text
# Sedmý demonstrační příklad
# vytvoření widgetu text
text .text -background White -width 40 -height 24
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure red -foreground red -underline 1
.text tag configure magenta -foreground magenta -overstrike 1
.text tag configure green -foreground green -font "Helvetica 50"
.text tag configure blue -foreground blue -underline 0
.text tag configure cyan -foreground cyan -underline 1 -font "Courier 20"
.text tag configure raised -relief raised -borderwidth 2
.text tag configure sunken -relief sunken -borderwidth 2
.text tag configure center -justify center
.text tag configure left -justify left
.text tag configure right -justify right
.text tag configure sup -offset 3p
.text tag configure sub -offset -3p
# reakce na události
.text tag bind colorOnEnter <Any-Enter> ".text tag configure colorOnEnter -background red"
.text tag bind colorOnEnter <Any-Leave> ".text tag configure colorOnEnter -background {}"
# práce s widgetem
.text insert end "Red\n" red
.text insert end "Magenta\n" magenta
.text insert end "Blue\n" blue
.text insert end "Cyan\n" cyan
.text insert end "Green\n" green
.text insert end "Raised box\n" raised
.text insert end "\n"
.text insert end "Sunken box\n" sunken
.text insert end "\n"
.text insert end "Centered text\n" center
.text insert end "Left justificiation\n" left
.text insert end "Right justificiation\n" right
.text insert end "H"
.text insert end "2" sub
.text insert end "O\n"
.text insert end "E=mc"
.text insert end "2\n\n" sup
.text insert end "hyperlink\n" colorOnEnter
Obrázek 13: Screenshot sedmého demonstračního příkladu s widgetem text na Windows XP
Obrázek 14: Screenshot sedmého demonstračního příkladu s widgetem text na X Window systému
6. Další widgety vložené ve widgetu text
Do widgetu text je možné kromě textových řetězců vkládat i další objekty a widgety. Všechny tyto objekty se vytváří pomocí oken vkládaných do textu. Na dalších dvou programových řádcích je ukázáno, jak se do textu vkládá widget typu button. Velmi flexibilní je vložení plátna (canvasu) do textu nebo práce s obrázky – touto problematikou, která se často používá například při tvorbě prohlížečů dokumentace nebo nápovědy, se budeme zabývat v další kapitole.
button .text.button -text "Stiskni me" -command ".text insert end Stisk"
.text window create end -window .text.button
7. Obrázky ve widgetu text
Obrázky je možné do textu zadávat nepřímo, například pomocí widgetu label. Na dalším demonstračním příkladu je ukázáno, jakým způsobem se obrázek vytvoří (příkaz set image [image create photo -file amy.ppm -width 296 -height 343]
) přiřadí k widgetu label (příkaz label .text.label -image $image
) a následně se celý popisek s obrázkem vloží do textu (příkaz .text window create end -window .text.label
). Pixmapu obrázku je možné načíst z externích souborů, v základní verzi knihovny Tk je možné pracovat například s formáty GIF a PPM. S dalšími formáty se pracuje pomocí dalších balíků přiložených k distribuci Tcl, například se jedná o balík ::jpeg. Příklad, ve kterém se do widgetu text vloží obrázek a výše zmíněné tlačítko (button), může vypadat například následovně:
#!/usr/bin/wish
# Použití widgetu text
# Osmý demonstrační příklad
# vytvoření widgetu text
text .text -background White -width 80 -height 50
# vložení widgetu text do jediného okna aplikace
pack .text
# nastavení tagů
.text tag configure red -foreground red -underline 1
.text tag configure magenta -foreground magenta -overstrike 1
.text tag configure green -foreground green -font "Helvetica 50"
.text tag configure blue -foreground blue -underline 0
.text tag configure cyan -foreground cyan -underline 1 -font "Courier 20"
.text tag configure raised -relief raised -borderwidth 2
.text tag configure sunken -relief sunken -borderwidth 2
.text tag configure center -justify center
.text tag configure left -justify left
.text tag configure right -justify right
.text tag configure sup -offset 3p
.text tag configure sub -offset -3p
# další widgety vložené do widgetu text
set image [image create photo -file amy.ppm -width 296 -height 343]
label .text.label -image $image
button .text.button -text "Stiskni me" -command ".text insert end Stisk"
# reakce na události
.text tag bind colorOnEnter <Any-Enter> ".text tag configure colorOnEnter -background red"
.text tag bind colorOnEnter <Any-Leave> ".text tag configure colorOnEnter -background {}"
# práce s widgetem
.text insert end "Red\n" red
.text insert end "Magenta\n" magenta
.text insert end "Blue\n" blue
.text insert end "Cyan\n" cyan
.text insert end "Green\n" green
.text insert end "Raised box\n" raised
.text insert end "\n"
.text insert end "Sunken box\n" sunken
.text insert end "\n"
.text insert end "Centered text\n" center
.text insert end "Left justificiation\n" left
.text insert end "Right justificiation\n" right
.text insert end "H"
.text insert end "2" sub
.text insert end "O\n"
.text insert end "E=mc"
.text insert end "2\n\n" sup
.text insert end "hyperlink\n" colorOnEnter
.text window create end -window .text.label
.text window create end -window .text.button
Obrázek 15: Screenshot osmého demonstračního příkladu s widgetem text na Windows XP
Obrázek 16: Screenshot osmého demonstračního příkladu s widgetem text na X Window systému
8. Dodatek k předchozí části
V předchozí části tohoto seriálu jsme si ukazovali, jakým způsobem je možné použít widget canvas (plátno) pro vytvoření jednoduchého grafického editoru. Popsaný editor však nedisponoval možností nazývanou „pružná úsečka“ – jedná se o úsečku (nebo jiný tvar), který se zobrazuje přímo při kreslení objektu.
Princip úpravy je díky některým vlastnostem plátna velmi jednoduchý. Základem je reakce na pohyb kurzoru myši. Pokud je na událost typu Motion navázána nějaká procedura, je tato procedura zavolána vždy, když uživatel pohybuje nad daným objektem kurzorem myši (pro každý objekt může být zaregistrována jiná procedura). Proceduře se přitom vždy předají souřadnice kurzoru vztažené relativně k počátku objektu. Pokud navážeme událost typu Motion k plátnu (například na proceduru nazvanou onMotion), musíme ještě rozlišit, zda je v dané chvíli stisknuto levé tlačítko myši, protože se tato událost generuje i v případě, že žádné tlačítko stisknuto není. K tomuto účelu je v programu použita globální proměnná button, která pro jednoduchost nabývá hodnoty jedna, pokud je levé tlačítko stisknuto, a hodnoty nula, pokud tomu tak není. Vykreslování „pružné úsečky“ se děje právě v proceduře onMotion, přičemž se za počáteční vrchol úsečky bere bod, ve kterém se nacházel kurzor myši při stisknutí levého tlačítka myši – tyto souřadnice jsou uloženy v globálních proměnných x1 a y1.
Aby vše nebylo jen tak jednoduché, musíme při každém pohybu myši vyřešit smazání předchozí „pružné úsečky“. Z tohoto důvodu je identifikátor úsečky zapamatován v globální proměnné usecka, ze které se v proceduře onMotion identifikátor přečte a úsečka se smaže. Současně se vytvoří úsečka nová, jejíž koncový bod je posunut do aktuálních souřadnic kurzoru myši.
#!/usr/bin/wish
# Jednoduchý grafický editor založený na widgetu canvas
# úprava editoru tak, aby podporoval zobrazení "pružných úseček"
# během kreslení. "Pružné úsečky" jsou vykreslovány červenou
# barvou, již nakreslené entity potom barvou černou.
# globální proměnné
set x1 0
set y1 0
set usecka 0
set button 0
# kontejner pro vkládání dalších widgetů
frame .editor
# plátno, na které se bude kreslit
canvas .editor.platno -width 512 -height 384
# vložení všech widgetů do okna aplikace
pack .editor
pack .editor.platno
# navázání událostí od myši
bind .editor.platno <ButtonPress-1> { onStart %x %y }
bind .editor.platno <ButtonRelease-1> { onStop %x %y }
bind .editor.platno <Motion> { onMotion %x %y }
# procedura, která je zavolána v případě,
# že uživatel stiskne levé tlačítko myši
proc onStart { x y } {
# zapamatování polohy kurzoru myši
global x1
global y1
global button
global usecka
set x1 $x
set y1 $y
set button 1
# set usecka [.editor.platno create line $x $y $x $y -fill red]
}
# procedura, která je zavolána v případě,
# že uživatel pustí levé tlačítko myši
proc onStop { x y } {
global x1
global y1
global button
set button 0
.editor.platno create line $x1 $y1 $x $y
}
# procedura, která je zavolána v případě,
# že uživatel pohybuje korzorem myši
proc onMotion { x y } {
global x1
global y1
global button
global usecka
# pokud je tlačítko myši stisknuto, vykreslí se pružná úsečka
if ($button) {
.editor.platno delete $usecka
set usecka [.editor.platno create line $x1 $y1 $x $y -fill red]
}
}
Obrázek 17: Screenshot upravené verze grafického editoru na Windows XP
Obrázek 18: Screenshot upravené verze grafického editoru na X Window systému
9. Obsah dalšího pokračování tohoto seriálu
V navazující části si povíme, jakým způsobem je možné do aplikací vytvořených pomocí Tcl/Tk zabudovat systém menu.