Hlavní navigace

Programovací jazyk TCL (8)

6. 9. 2005
Doba čtení: 9 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 zejména způsobem práce s grafikou. Ukážeme si použití velmi flexibilního widgetu canvas a také práci s bitmapami i vícebarevnými obrázky.

Obsah

1. Způsob práce s grafikou v knihovně Tk
2. Widget canvas
3. Použití widgetu canvas
4. Objekt typu image
5. Objekt typu bitmap
6. Objekt typu photo
7. Použití widgetu image
8. Obsah dalšího pokračování tohoto seriálu

1. Způsob práce s grafikou v knihovně Tk

Největší přínos většiny grafických uživatelských rozhraní spočívá v možnosti jednoduché a názorné práce s grafickými informacemi. V knihovně/toolkitu Tk je samozřejmě práce s grafikou podporovaná velmi dobře, zejména v porovnání se stávajícími aplikačními rozhraními či toolkity. Mnohé toolkity dokonce práci s grafikou nepodporují vůbec nebo nabízejí pouhé objektové „obalení“ funkcí z knihoven na nižší úrovni – dobrým příkladem tohoto řešení může být knihovna VCL (Visual Component Library) firmy Borland, která obsahuje určité objekty a metody pro práci s grafikou vytvářenou na canvasu, veškeré volání těchto metod je však prováděno přímo voláním funkcí z Windows API. Toolkit Tk práci s grafikou pojímá jinak – grafický výstup není pouze „write only“, protože s grafickými objekty lze i po jejich vykreslení manipulovat.

Práci s grafikou můžeme chápat ve dvou úrovních. Na vyšší úrovni manipulujeme s jednotlivými geometricky popsanými tvary, jakými jsou například úsečka, obdélník, kruh, text či spline křivka. Každému tvaru může být přiřazeno značné množství atributů, jedná se například o tloušťku čáry, kterou je vykreslena hranice objektu, barva a styl výplně uzavřených objektů či font vykreslovaného textu. Na úrovni nižší se může pracovat přímo s pixely, které tvoří zobrazovaný rastrový obrázek. V knihovně Tk je pro práci na vyšší úrovni určen widget canvas spolu s dalšími objekty, na nižší úrovni pak widgety (resp. objekty) bitmap, image a photo. Objekt typu image přitom zapouzdřuje více typů obrázků, odbitmap přes vícebarevný photo až po uživatelsky vytvářené formáty.

2. Widget canvas

Jak jsme si již řekli v předchozí kapitole, je pro práci s grafikou na vyšší úrovni nabízen v knihovně Tk widgetcanvas, česky bychom mohli tento název přeložit jako (malířské) plátno. Nenechte se zmýlit tímto názvem, který má v jiných programových knihovnách jiný (většinou jednodušší) význam, zde se jedná o velmi mocný widget, který současně slouží jako kontejner pro další objekty. Vkládané objekty si své vlastnosti zachovávají, tj. lze s nimi interaktivně i programově pohybovat, měnit jejich vlastnosti apod. K tomu musíme připočítat možnost uložit celé plátno do PostScriptového souboru se zachováním vektorových charakteristik plátna (tj. neprovádí se ztrátový převod na bitmapy). Každý objekt, který je na plátno umístěn, musí mít specifikovány souřadnice počátečního a koncového bodu, v případě lomených čar, spline křivek a polygonů se samozřejmě specifikuje bodů více. Souřadnice bodů mohou být zadány pomocí více jednotek, jež se rozlišují podle jednoho písmene zapsaného za numerickou hodnotou (hodnoty jsou samozřejmě platné pouze při správně nakalibrované obrazovce, což kupodivu mnoho systémů dodnes nedodržuje):

Jednotky používané pro specifikaci souřadnic bodů na plátně
Přípona Význam
m milimetry
c centimetry
i palce
p body (implicitní hodnota)

V následujícím příkladu je ukázáno jednoduché použití plátna, na které jsou pomocí metody create vloženy jednoduché objekty – úsečka, kruh a text. Vzhledem k tomu, že se při specifikaci souřadnic neuvádí u číselných hodnot žádná přípona, předpokládá se, že jsou všechny hodnoty zapsány v bodech (pixelech). To také znamená, že na různých obrazovkách a při různých rozlišeních budou mít nakreslené objekty jinou velikost, což nám v tomto případě nemusí vadit.

#!/usr/bin/wish

# první demonstrační příklad

# vytvoříme plátno
canvas .platno -width 256 -height 256

# vložíme plátno do okna
grid .platno -column 1 -row 1

# na plátnu vytvoříme několik objektů
.platno create oval 10 10 100 100
.platno create line 0 0 255 255
.platno create line 0 255 255 0
.platno create text 50 120 -text "Hello world" 
TCL 8a

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

Vkládané objekty mohou mít nastaveno velké množství vlastností, jak je ukázáno na modifikaci předchozího příkladu (nejsou zde ukázány zdaleka všechny vlastnosti, ty jsou uvedeny a podrobně popsány v helpu):

#!/usr/bin/wish

# druhý demonstrační příklad

# vytvoříme plátno
canvas .platno -width 256 -height 256

# vložíme plátno do okna
grid .platno -column 1 -row 1

# na plátnu vytvoříme několik objektů
# se změněnými vlastnostmi
.platno create oval 10 10 100 100 -fill red -outline blue -width 3
.platno create line 0 0 255 255 -width 5
.platno create line 0 255 255 0 -dash 123
.platno create text 150 120 -text "Hello world" -fill white -font "Helvetica 20" 
TCL 8b

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

3. Použití widgetu canvas

Z demonstračních příkladů uvedených v předchozí kapitole je patrné, jakým způsobem je možné nastavit barvu obrysu (volba -outline barva), šířku obrysu (volba -width tloušťka), způsob vykreslení čar (volba -dash vzorek) a barvu výplně (volba -fill barva). Možnosti nastavení se samozřejmě liší podle typu vkládaného objektu, například pro čáry není možné specifikovat barvu výplně apod. V následující tabulce je ukázáno, jaké objekty je možné na plátno pokládat (příkazem jméno_plátna create jméno_objektu):

Objekty, které lze pokládat na plátno (canvas)
Jméno objektu Význam
arc kruhový nebo eliptický oblouk
bitmap bitmapový obrázek
image obecně vícebarevný rastrový obrázek
line úsečka, lomená úsečka nebo dokonce hladká spline křivka (!)
oval uzavřená kružnice nebo elipsa
polygon uzavřený polygon či tvar vytvořený ze spline křivek
rectangle čtverec nebo obdélník
text textový řetězec
window vnořené okno se samostatným řízením

Při vkládání objektů na plátno je možné specifikovat i jejich jmenovku (tag), pomocí které je možné objektům přiřadit nějaké vlastnosti či na ně navázat události. Každému objektu dokonce může být přiřazeno jmenovek více. Jmenovky se používají zejména při hromadné změně vlastností objektů. Nejprve si vytvořme plátno (canvas), na které položíme čtyři kruhy vybarvené modře. Tyto kruhy mají přiřazenu stejnou jmenovku – mujObjekt.

#!/usr/bin/wish

# třetí demonstrační příklad

# vytvoříme plátno
canvas .platno -width 256 -height 256

# vložíme plátno do okna
grid .platno -column 1 -row 1

# na plátnu vytvoříme několik objektů se jmenovkou
.platno create oval  10  10 110 110 -tags mujObjekt -fill blue
.platno create oval 150  10 250 110 -tags mujObjekt -fill blue
.platno create oval  10 150 110 250 -tags mujObjekt -fill blue
.platno create oval 150 150 250 250 -tags mujObjekt -fill blue 

Předchozí demonstrační příklad můžeme upravit tak, že přidáme ovladače dvou událostí. První událost nastane v případě, že uživatel na některý objekt najede kurzorem myši (Enter), druhá událost naopak nastane při odjetí kurzoru mimo daný objekt (Leave). Vzhledem k tomu, že je všem čtyřem kruhům nastavena stejná jmenovka, je možné obsluhu událostí napsat pouze jednou:

#!/usr/bin/wish

# čtvrtý demonstrační příklad

# vytvoříme plátno
canvas .platno -width 256 -height 256

# vložíme plátno do okna
grid .platno -column 1 -row 1

# na plátnu vytvoříme několik objektů se jmenovkami
.platno create oval  10  10 110 110 -tags mujObjekt -fill blue
.platno create oval 150  10 250 110 -tags mujObjekt -fill blue
.platno create oval  10 150 110 250 -tags mujObjekt -fill blue
.platno create oval 150 150 250 250 -tags mujObjekt -fill blue

# připojení událostí k objektům se jmenovkou mujObjekt
.platno bind mujObjekt <Enter> ".platno itemconfigure current -fill red"
.platno bind mujObjekt <Leave> ".platno itemconfigure current -fill blue" 

Troufnu si tvrdit, že výše uvedený příklad není možné snad v žádném jiném toolkitu napsat jednodušším způsobem. Popravdě řečeno, i zde by se dal příklad zkrátit, například vložením souřadnic kruhů do seznamu a jejich následným vytvořením pomocí jedné smyčky typu foreach.

TCL 8c

Obrázek 3: screenshot čtvrtého demonstračního příkladu (bez zobrazeného kurzoru myši)

4. Objekt typu image

Objekt typu image slouží k vytváření a manipulaci s rastrovými obrázky, a to jak s bitmapami (jednobarevnými obrázky), tak i s pixmapami (obecně vícebarevnými obrázky, ať již s barvovou paletou, či bez ní). O vytvoření objektu image se stará příkaz:

image create typ_obrázku -parametry 

Tento příkaz vrací identifikátor objektu, který si pro další použití, například nastavování parametrů či ukládání obrázku na disk, musíme uchovat v nějaké proměnné. V praxi se proto většinou používá tento idiom:

set proměnná [image create typ_obrázku -parametry] 

například:

set imageVar [image create photo -width 800 -height 600] 

K další manipulaci s obrázky slouží následující příkazy:

Příkazy pro manipulaci s obrázky
Příkaz Význam
image create vytvoření obrázku (popsáno výše)
image delete vymazání objektu s obrázkem
image height vrací šířku obrázku
image width vrací výšku obrázku
image names vrací seznam všech obrázků
image types vrací typy všech validních obrázků

V dalších kapitolách si probereme dva nejpoužívanější formáty obrázků – bitmap a photo.

5. Objekt typu bitmap

Objekt typu bitmap slouží k manipulaci s dvoubarevnými rastrovými obrázky, u kterých je každý pixel reprezentován pouze jedním bitem – může tedy nabýt pouze dvou hodnot. Výhodou bitmap je jejich takřka absolutní přenositelnost mezi různými platformami s grafickým uživatelským rozhraním, protože alespoň dvě barvy dokáže zobrazit každé grafické zařízení (dívat se na jednobarevnou plochu je trošku nudné :-). V pojetí Tk však mohou být bitmapy komplikovanější, protože je podporována i transparentnost. Ta je řešena pomocí dvojice bitmap, kde první bitmapa obsahuje vlastní obrázek a druhá bitovou masku specifikující, které pixely mají být vykresleny a u kterých se má ponechat původní hodnota. Podrobnější informace o bitmapách si řekneme v dalších pokračováních tohoto seriálu.

6. Objekt typu photo

Objekt typu photo slouží k manipulaci s vícebarevnými obrázky. Způsob zobrazení těchto objektů se může na různých systémech lišit, zejména je nutné brát v úvahu barevnou hloubku zobrazení (tj. počet bitů na jeden pixel). Implicitně se objekt typu photo vytváří při běhu aplikace tak, aby co nejvíce odpovídal nastavení konkrétního systému, toto chování je však možné změnit a například vždy pracovat s osmibitovou barevnou hloubkou (vhodné pro obrázky s paletou). Mimo nastavování a čtení barev jednotlivých pixelů je umožněno, aby se obrázek načetl či uložil do externího souboru. Spolu s Tcl/Tk jsou dodávány filtry pro práci s formáty PPM (Portable PixelMap), PGM(Portable GrayMap) a GIF (Graphics Interchange Format). I o těchto objektech si v dalších dílech seriálu řekneme podrobnější informace.

7. Použití widgetu image

V následujícím příkladu je ukázáno, jakým způsobem se může vytvořit „plnobarevný“ rastrový obrázek. Obrázek má velikost 256×256 pixelů a jedná se o jediný widget, který je v okně grafického shellu wish zobrazen. Pomocí podfunkce put se v obrázku nastavují barvy jednotlivých pixelů, v našem případě je barva kódována stejným způsobem jako v HTML stránkách – za znakem # je uvedena trojice hexadecimálních číslic 00-FF, každá číslice odpovídá jedné barvové složce R (red), G (green) a B (blue). Formátování obstarává příkaz format, který akceptuje podobné parametry jako C-čkovská funkce printf().

#!/usr/bin/wish

# pátý demonstrační příklad

# rozměry obrázku
set width  256
set height 256

# vytvoření plátna
canvas .canvas -width $width -height $height
pack   .canvas -fill both

# vytvoření obrázku
set image [image create photo -width $width -height $height]
$image blank

# vložení obrázku na plátno
.canvas create image 0 0 -image $image -anchor nw

# naplnění pixelů v obrázku
for {set row 0} {$row<$height} {incr row} {
    for {set col 0} {$col<$width} {incr col} {
        # barva obrázku v HTML stylu
        set colour [format "#%02X%02X%02X" $col $row 0]
        # zapsat barvu pixelu
        $image put $colour -to $col $row
    }
} 
TCL 8d

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

CS24_early

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

V dalším pokračování tohoto seriálu ještě neopustíme část věnovanou grafice, protože si podrobně popíšeme objekty, které lze vkládat na plátno. Také si vytvoříme velmi jednoduchý vektorový editor ve stylu CorelDraw 0.1 Alpha :-).

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.