Hlavní navigace

Programovací jazyk TCL (15)

Pavel Tišnovský 25. 10. 2005

V dnešním pokračování seriálu o programovacím jazyku Tcl a toolkitu pro programování grafického uživatelského rozhraní Tk si ukážeme způsob vytváření nových modálních i nemodálních oken pomocí widgetu/kontejneru nazvaného příznačně toplevel. Také si ukážeme, jakým příkazem je možné zařídit změnu vlastností nově vytvářených oken a dokonce i změnu celého barevného schématu aplikace.

Obsah

1. Vytváření nových oken
2. Nemodální okna
3. Modální okna
4. Další vlastnosti oken
5. Změna barevného schématu aplikace
6. Obsah dalšího pokračování tohoto seriálu

1. Vytváření nových oken

V prakticky všech demonstračních příkladech uvedených v předchozích částech tohoto seriálu jsme pracovali s aplikací, která obsahovala pouze jedno okno (tím pádem se jednalo o okno hlavní). V praxi však obsahuje velká část aplikací s grafickým uživatelským rozhraním oken více – ať se již jedná o okna potřebná pro zobrazení zpracovávaných dokumentů (jedná se o aplikace typu SDI a MDI), nebo o okna fungující jako dialogy či konfigurační listy. První náznak toho, že Tcl/Tk s více okny dokáže pracovat, jsme viděli v demonstračních příkladech, které používaly buď rolovací, nebo vyskakovací menu – tato menu bylo možné při správném nastavení (tj. specifikaci vlastnosti -tearoff 1) „odtrhnout“ z jejich původní pozice a používat jako další okna se zobrazeným seznamem příkazů. Druhým náznakem práce s více okny bylo použití standardních dialogových oknech, které jsme si předváděli v předchozí části tohoto seriálu. Dnes si ukážeme, jakým způsobem je možné vytvářet plnohodnotná okna, tj. okna, která mohou obsahovat libovolnou směsici widgetů. Tím se tato okna podstatně odlišují od standardních dialogů, jejichž obsah byl do značné míry omezen.

Základem modálních i nemodálních oken je widget nazvaný toplevel. Tento widget se chová podobně jako dříve popsaný widget frame (tj. jedná se o kontejner), ale s tím podstatným rozdílem, že se nezobrazí ve svém rodičovském okně, ale v okně samostatném. Vlastnosti tohoto widgetu si ukážeme v následujících třech kapitolách: ve druhé kapitole se budeme zabývat nemodálními okny, v kapitole třetí okny modálními a konečně si ve čtvrté kapitole ukážeme možnosti změny některých vlastností oken.

2. Nemodální okna

Nemodální okna se vytvoří velmi jednoduše zavoláním příkazu toplevel, který po svém zavolání vygeneruje nové okno, jež se chová jako kontejner, tj. je do něj možné vkládat další widgety. V příkazu toplevel se musí specifikovat název (identifikace) nového okna, které se, stejně jako při zadávání názvů widgetů, udává ve tvaru plné cesty začínající kořenem označeným symbolem „.“ (tečka). Ihned po vytvoření nového okna se na něj dají vkládat další widgety. Při práci s dialogovými okny (ať už modálními, či nemodálními) uživatel očekává, že se tato okna zobrazí nad ostatními okny. To v Tcl/Tk zařizuje příkaz raise, opakem je příkaz lower (tyto příkazy ovšem fungují stejným způsobem i pro jiné widgety, které se tak mohou na jednom kontejneru překrývat). Posledním příkazem nutným pro vytvoření nemodálního okna je příkaz tkwait, který zajistí, že se běh části programu ovládajícího okno pozastaví, a počká se tak na vstup od uživatele. Vzhledem k tomu, že je nově vytvořené okno nemodální, může uživatel pracovat i s ostatními okny v aplikaci. Všechny výše uvedené příkazy jsou použity i v prvním demonstračním příkladu:

#!/usr/bin/wish

# Vytváření nových oken v Tcl/Tk
# První demonstrační příklad

# vytvoření dvou příkazových tlačítek
button .window -text "Vytvoř nové okno" -command {newWindow}
button .quit   -text "Konec" -command {exit}

# vytvoření popisky hlavního okna
label .label -text "Hlavní okno aplikace"

# vložení všech widgetů do hlavního okna
pack .label  -fill both
pack .window -fill both
pack .quit   -fill both

# procedura pro vytvoření nového okna
proc newWindow {} {
    toplevel .newwin
    label    .newwin.label -text "Nové okno"
    button   .newwin.close -text "Zavři okno" -command {destroy .newwin}
    pack  .newwin.label
    pack  .newwin.close
    raise .newwin
    tkwait window .newwin
}

# finito 
TCL 15 - 1

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

TCL 15 - 2

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

3. Modální okna

Modální okna, jejichž výskyt v aplikacích je z uživatelského hlediska dobré co nejvíce omezit, se tvoří poněkud složitějším způsobem než okna nemodální. Je to z toho důvodu, že musíme GUI systému explicitně specifikovat, že modální okno po dobu své existence přebírá uživatelský vstup, zatímco ostatní okna aplikace nebudou uživateli dostupná (to se však netýká vstupu pro ostatní aplikace, i když i ten je možné zakázat). Ve druhém demonstračním příkladu je ukázán jeden ze způsobů vytvoření modálního okna. Jedná se zejména o čtveřici příkazů:

  1. grab .newwin – nové okno .newwin získá výlučný přístup k událostem od uživatele
  2. raise .newwin – nové okno .newwin je zobrazeno nad ostatními okny aplikace
  3. focus .newwin – nové okno .newwin získá fokus, tj. uživatelský vstup
  4. tkwait window .newwin – aplikace vyčká na uzavření okna .newwin

Na tomto místě je nutné upozornit na fakt, že pokud okno nebude obsahovat prvek pro své uzavření, může být běh aplikace „zacyklen“ a okno musí být násilně uzavřeno například pomocí ikony pro zrušení okna („křížek“¨).

#!/usr/bin/wish

# Vytváření nových oken v Tcl/Tk
# Druhý demonstrační příklad

# vytvoření dvou příkazových tlačítek
button .window -text "Vytvoř nové okno" -command {newWindow}
button .quit   -text "Konec" -command {exit}

# vytvoření popisky hlavního okna
label .label -text "Hlavní okno aplikace"

# vložení všech widgetů do hlavního okna
pack .label  -fill both
pack .window -fill both
pack .quit   -fill both

# procedura pro vytvoření nového okna
proc newWindow {} {
    toplevel .newwin
    label .newwin.label -text "Nové okno"
    button .newwin.close -text "Zavři okno" -command {destroy .newwin}
    pack .newwin.label
    pack .newwin.close
    # nastavení modálního okna
    grab .newwin
    raise .newwin
    focus .newwin
    tkwait window .newwin
}

# finito 
TCL 15 - 3

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

TCL 15 - 4

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

Předchozí příklad je možné ještě vylepšit tak, aby aplikace korektně reagovala i v případě, že je okno uživatelem uzavřeno nestandardním způsobem (například ikonou „křížku“ či podobným ovládacím prvkem). Zde stačí pomocí callback funkce navázat na událost WM_DELETE_WINDOW, při jejímž výskytu se zruší výlučný přístup okna k uživatelskému vstupu a okno je posléze zrušeno pomocí příkazu destroy název_okna. Také je nastaven předek okna pomocí příkazu wm transient název_okna název_předka.

#!/usr/bin/wish

# Vytváření nových oken v Tcl/Tk
# Třetí demonstrační příklad

# vytvoření dvou příkazových tlačítek
button .window -text "Vytvoř nové okno" -command {newWindow}
button .quit   -text "Konec" -command {exit}

# vytvoření popisky hlavního okna
label .label -text "Hlavní okno aplikace"

# vložení všech widgetů do hlavního okna
pack .label  -fill both
pack .window -fill both
pack .quit   -fill both

# procedura pro vytvoření nového okna
proc newWindow {} {
    toplevel .newwin
    label .newwin.label -text "Nové okno"
    button .newwin.close -text "Zavři okno" -command {destroy .newwin}
    pack .newwin.label
    pack .newwin.close
    # nastavení modálního okna
    grab .newwin
    wm protocol .newwin WM_DELETE_WINDOW {grab release .newwin; destroy .newwin}
    wm transient .newwin .
    raise .newwin
    focus .newwin
    tkwait window .newwin
}

# finito 
TCL 15 - 5

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

TCL 15 - 6

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

4. Další vlastnosti oken

Po vytvoření okna je možné měnit velké množství jeho vlastností. Ty se nenastavují přímo příkazem configure, jak jsme byli zvyklí u ostatních widgetů, ale pomocí „Správce oken“ (Window Manageru), který je v Tcl/Tk reprezentován objektem wm. Nastavení vlastnosti okna se provádí pomocí příkazu:

wm vlastnost jméno_okna hodnoty_vlastnosti 

U systémově závislých vlastností nastavovaných pomocí attributes je syntaxe poněkud odlišná:

wm attributes jméno_okna vlastnost hodnota_vlastnosti 

V následující tabulce jsou vypsány nejdůležitější vlastnosti oken, které se mohou měnit přes správce oken wm.

Vlastnosti oken
Název vlastnosti Význam
attributes -disabled nastavení okna do stavu disabled (týká se i widgetů na okně) – v některých případech nepracuje korektně
attributes -toolwindow nastavení stylu okna tak, aby se podobalo „nástrojovému“ dialogu podle specifikace MSDN (funguje pouze na MS Windows)
attributes -topmost okno bude zobrazeno nad všemi ostatními okny (dosti otravná vlastnost, doporučuji nepoužívat)
attributes -modified nastavení indikátoru uzavření okna na Mac OS X (na ostatních systémech nemá význam)
attributes -alpha nastavení průhlednosti okna mezi 0% (α=0.1) až 100% (α=1.0)
focusmodel nastavení aktivního nebo pasivního řízení fokusu
geometry nastavení aktuální velikosti a pozice okna na obrazovce
maxsize nastavení maximální povolené velikosti okna
minsize nastavení minimální povolené velikosti okna
resizable povolení nebo zakázání uživatelské změny velikosti okna
state změna stavu okna mezi: normal, iconic, withdrawn a icon
title nastavení titulku okna
transient změna předka okna

Ve čtvrtém demonstračním příkladu je ukázáno, jakým způsobem je možné změnit průhlednost okna pomocí příkazu wm attributes jméno_okna -alpha. Tento příkaz však pracuje korektně pouze v některých GUI systémech, které průhlednosti oken podporují. Jedná se například o Mac OS X, Microsoft Windows 2000 a Microsoft Windows XP.

#!/usr/bin/wish

# Vytváření nových oken v Tcl/Tk
# Čtvrtý demonstrační příklad

# vytvoření dvou příkazových tlačítek
button .window -text "Vytvoř nové okno" -command {newWindow}
button .quit   -text "Konec" -command {exit}

# vytvoření popisky hlavního okna
label .label -text "Hlavní okno aplikace"

# vložení všech widgetů do hlavního okna
pack .label  -fill both
pack .window -fill both
pack .quit   -fill both

# procedura pro vytvoření nového okna
proc newWindow {} {
    toplevel .newwin
    label .newwin.label -text "Nové okno"
    button .newwin.close -text "Zavři okno" -command {destroy .newwin}
    pack .newwin.label
    pack .newwin.close
    # nastavení modálního okna
    grab .newwin
    wm protocol .newwin WM_DELETE_WINDOW {grab release .newwin; destroy .newwin}
    wm attributes .newwin -alpha 0.8
    wm transient .newwin .
    raise .newwin
    focus .newwin
    tkwait window .newwin
}

# finito 
TCL 15 - 7

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

5. Změna barevného schématu aplikace

Jak již víme z předchozích částí tohoto seriálu, je možné u téměř každého vytvářeného widgetu či jeho části (například položky menu) měnit mnoho vlastností, a to i barvu popředí a pozadí. Toolkit Tk však obsahuje také mechanismus pro globální změnu barev v rámci celé aplikace – výhodou je zjednodušení programového kódu a také jednodušší změna barev, která se provádí na jednom místě. Množinu všech základních barev použitých při vytváření widgetů, která se nazývá barevné schéma, je možné měnit pomocí následující trojice příkazů:

tk_bisque
tk_setPalette background
tk_setPalette jméno hodnota ... 

Nejjednodušší je příkaz tk_bisque. Po jeho zadání se změní barevné schéma tak, aby aplikace vypadala podobně jako v Tcl/Tk verze 3.6 a nižší. Výsledkem použití tohoto příkazu je aplikace, jejíž GUI prvky mají nádech světlehnědého porcelánu. Ostatní dva příkazy umožní měnit barvy jednotlivých částí widgetů – pozadí, popředí, textu, 3D rámečku atd. Pokud se za příkaz tk_setPalette uvede pouze jedna barva, pokusí se Tcl/Tk ostatní barvy dopočítat tak, aby výsledkem byla „rozumně“ vypadající aplikace. Je však také možné uvést barev více, každou pro jednu z těchto položek (opět platí, že ne všechny položky musí být uvedeny):

  1. activeBackground
  2. foreground
  3. selectColor
  4. activeForeground
  5. highlightBackground
  6. selectBackground
  7. background
  8. highlightColor
  9. selectForeground
  10. disabledForeground
  11. insertBackground
  12. troughColor

Barva může být specifikována jak svou hodnotou (například po vzoru jazyka HTML), tak i svým symbolickým jménem. Jména všech barev jsou uvedena v nápovědě spolu s hodnotami svých barvových složek R, G a B. Příklad použití příkazu tk_setPalette:

tk_setPalette darkviolet 

nebo:

tk_setPalette steelblue 
TCL 15 - 8

Obrázek 8: Nastavení barevného schématu na ‚darkviolet‘

TCL 15 - 9

Obrázek 9: Nastavení barevného schématu na ‚steelblue‘

TCL 15 - 10

Obrázek 10: Nastavení barevného schématu na ‚tk_bisque‘

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

V následujícím pokračování tohoto seriálu si ukážeme práci s GUI knihovnami BWidgets a IWidgets, které tvoří rozšíření základního toolkitu Tk.

Našli jste v článku chybu?

25. 10. 2005 11:50

jirka b. (neregistrovaný)
Děkuji za povídání o těch oknech - večer si to vyzkouším. To vaše řešení vypadá velmi elegantně. Já jsem si nevšimnul Vaší otázky pod minulých článkem, proto reaguji až teď. Takže zatím to dělám takhle divně pomocí kódu (někde jsem to vygoogloval):
toplevel $dialog -takefocus 1
wm title $dialog [format "Node %i" $id]
wm transient $dialog .

# nějaký kód...

tkwait visibility .
grab $dialog
wm transient $dialog .
wm protocol $dialog WM_DELETE_WINDOW {grab release $dialog; destro…
Vitalia.cz: Pečete cukroví a zbyl vám bílek?

Pečete cukroví a zbyl vám bílek?

120na80.cz: Rakovina oka. Jak ji poznáte?

Rakovina oka. Jak ji poznáte?

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Vitalia.cz: Chtějí si léčit kvasinky. Lék je jen v Německu

Chtějí si léčit kvasinky. Lék je jen v Německu

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Podnikatel.cz: Víme první výsledky doby odezvy #EET

Víme první výsledky doby odezvy #EET

Lupa.cz: Babiš: E-shopů se EET možná nebude týkat

Babiš: E-shopů se EET možná nebude týkat

Podnikatel.cz: EET: Totálně nezvládli metodologii projektu

EET: Totálně nezvládli metodologii projektu

Lupa.cz: Insolvenční řízení kvůli cookies? Vítejte v ČR

Insolvenční řízení kvůli cookies? Vítejte v ČR

DigiZone.cz: Flix TV má set-top box s HEVC

Flix TV má set-top box s HEVC

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu

Vitalia.cz: Jsou čajové sáčky toxické?

Jsou čajové sáčky toxické?

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Lupa.cz: Seznam mění vedení. Pavel Zima v čele končí

Seznam mění vedení. Pavel Zima v čele končí

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

120na80.cz: Horní cesty dýchací. Zkuste fytofarmaka

Horní cesty dýchací. Zkuste fytofarmaka

Podnikatel.cz: 1. den EET? Problémy s pokladnami

1. den EET? Problémy s pokladnami

Měšec.cz: Finančním poradcům hrozí vracení provizí

Finančním poradcům hrozí vracení provizí

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

120na80.cz: Boreliózu nelze žádným testem prokázat

Boreliózu nelze žádným testem prokázat