SOP121/ćw - temat E.

Język skryptowy TCL/TK.

Skrót TCL oznacza "Tool Command Language".

TCL jest językiem skryptowym, podobnym do języków powłok Unixa (takich jak ksh, bash, csh). Podstawowym pojęciem języka jest komenda. Zasadniczo, w tym języku nie ma nic oprócz komend !. Podstawowym "typem danych" jest string.

Skrót TK oznacza "ToolKit", czyli bibliotekę do tworzenia okienkowego interfejsu użytkownika, przy pomocy tzw widgetów, pod XWindows. TK jest dużo łatwiejsze w użyciu niż biblioteki takie jak np XtIntrinsics !. Jest powszechnie wiadome, że przy pomocy TK można skonstruować skomplikowany interfejs użytkownika, w zdumiewająco krótkim czasie ...

Charakterystyczne cechy języka TCL:

  • Jest językiem interpretowanym (nie trzeba niczego kompilować).
  • Można pisać tradycyjne skrypty (działające w trybie "tekstowym") - używamy wtedy interpretera tclsh, lub można pisać skrypty komunikujące się z użytkownikiem za pomocą okienkowego interfejsu - używamy wtedy interpretera wish.
  • Skrypty TCL są przenośne: istnieją interpretery dla dowolnego Unixa, oraz dla platformy W95/NT.
  • Język TCL można rozszerzać na różne sposoby. Rozszerzanie polega zasadniczo na dodawaniu nowych komend. Można to robić z poziomu skryptu (komenda "proc") a także z poziomu języka C/C++ (nowe komendy wbudowane).
  • Istnieją mechanizmy ułatwiające używanie dużych rozszerzeń (zawierających wiele komend). Podstawowym rozszerzeniem TCL-u jest TK. Istnieje wiele innych rozszerzeń: BLT, TIX, ...
  • Można "zintegrować" TCL z aplikacją. TCL musi wtedy zostać rozszerzony o komendy pozwalające sterować aplikacją. TCL staje się wtedy językiem do komunikacji między aplikacjami (jedna aplikacja może wysłać drugiej skrypt do wykonania, następnie druga aplikacja wykonuje skrypt, następnie rezultat działania skryptu jest zwracany pierwszej aplikacji).
  • Filozofia dwujęzykowego tworzenia aplikacji: najpierw rozszerzamy TCL o odpowiednie "cegiełki", konkretne aplikacje są skryptami, zbudowanymi z owych cegiełek.
  • Istnieje potężne narzędzie do automatycznego przetwarzania źródeł danej biblioteki (w j. C/C++) na rozszerzenie TCL-u. Jest to program SWIG. Rozszerzenie zawierające bibliotekę OpenGL zostało zrobione właśnie w ten sposób !.
  • Aplety TCL/TK. Jeśli mamy odpowiednią wtyczkę (plug-in) do Netscape, to możemy umieszczać aplety w stronach, przy pomocy polecenia <embed plik.tcl>. Istnieją bardzo wyrafinowane mechanizmy bezpieczeństwa !.
  • Tradycyjnie, TCL/TK jest używane do unowocześniania "starych" aplikacji, takich jak np klient "ftp", wymagający wydawania komend open, get itp. Przy pomocy TCL/TK można z niego zrobić nowoczesną aplikację, komunikującą się z użytkowinikiem przy pomocy okienek, listbox-ów, scrollbar-ów itp ...

  •  

    Podstawy języka TCL.

    Podstawowym pojęciem TCL-u jest komenda. Program (skrypt) w TCL-u to po prostu tekst zawierający ciąg komend. Także instrukcje sterujące (np pętle) są w rzeczywistości komendami ...

    Dokumentacja TCL-TK:

  • [Unix] jeśli zainstalowano "tclX", to wygodny help jest dostępny przez program "tclhelp"; ponadto opisy komend są dostępne także w zwykłym manualu [rozdział "n"]; strony manuala znajdują się w katalogu /usr/share/man/mann (stad można brać nazwy komend Tcl-u)
  • [WinNT] help znajduje się w pliku "g:\app\dev\Tcl\doc\tcl82.hlp" (?)
  • oto prosta dokumentacja, jednej ze starszych wersji TCL
  • jeszcze inna dokumentacja "http://hermes.desy.de/tcl"

    Dokumentacja "ActiveTcl"; jest to Tcl v.8.4 z wieloma rozszerzeniami ...

  • http://ASPN.ActiveState.com/ASPN/docs/ActiveTcl

    Inne strony WWW poświęcone językowi TclTk :
  • http://www.tcltk.com (?)

    Sposoby uruchamiania skryptów w TCL-u:

  • interpreter TCL-u posiada konsolę, z której można uruchamiać dowolne komendy; w szczególności skrypty można uruchamiać przy pomocy komendy "source skrypt.tcl"
  • [Unix] należy wydać z xterm-u polecenie "wish" lub "tclsh" (bez parametrów); w xterm-ie z którego uruchomiliśmy interpreter pojawi się konsola
  • [WinNT] jak wyżej, z tym że interpreter znajduje się w pliku "g:\app\dev\Tcl\bin\wish82.exe" i "g:\app\dev\Tcl\bin\tclsh82.exe"; po uruchomieniu pojawia się osobne okienko z konsolą; skrypty można uruchamiać poleceniem "source" lub przy pomocy menu "File" (tylko "wish")
  • skrypt w TCL/TK zawierający udoskonaloną konsolę: konsola.tcl
  • inne metody uruchamiania skryptów ...

  • [Unix] można nadać plikowi ze skryptem prawo "x" oraz w pierwszej linii skryptu umieścić jedno z dwóch:
  •    #!/usr/bin/wish
       #!/usr/bin/tclsh
  • [Unix] można wydać następujące polecenie aby uruchomić "skrypt.tcl":
  •    wish skrypt.tcl
       tclsh skrypt.tcl
    Debuger TCL/TK (raczej dla zaawansowanych !):
    W pliku "tdebug.zip" znajduje się debuger który działa na wszystkich platformach (jest napisany w TCLu).
    Sposob uruchamiania debugera jeśli szukamy błędu w "plik.tcl":
    Można wykonywać krokowo jedynie procedury (zdefiniowane przez "proc"); należy je wcześniej wskazać w odpowiednim okienku; nie można debugować procedur obsługujących asynchronicznie pliki.

     

    Zadanie 70


    Naucz się języka TCL/TK wypróbowując poniższe przykłady (dłuższe z nich należy umieścić w skrypcie !).
    Komendy oraz wydruki ich działania umieść w sprawozdaniu !.
     

    Prosty przykład skryptu:

      # komentarz
      #
    
      set iloscObrotow 10
         # przypisywanie zmiennej "iloscObrotow" wartości "10"
    
      for {set i 1} {$i <= $iloscObrotow} {incr i} {
        puts "<<<$i>>>"
         # "puts" wyswietla napisy na terminalu
      }

    Substytucje komend.

    Każda komenda zwraca, po uruchomieniu, string.

    Jeśli w tekście skryptu zamieścimy komendę w nawiasach [], to komenda zostanie uruchomiona, a jej wynik zostanie wstawiony w miejsce napisu [komenda].
    Przykład:

      puts "wynik operacji 1+1 = [expr 1+1]"
        # "expr" to komenda do obliczania wartości wyrażeń arytmetycznych
        # wynik: wynik operacji 1+1 = 2

    Substytucje zmiennych.

    Substytucje zmiennych to zastępowanie napisu "$nazwa_zmiennej" wartością tej zmiennej.
    Przykład:
      set zmienna1 "qqq www eee"
      set zmienna2 {qqq www eee}
      puts "zmienna1=$zmienna1, zmienna2=$zmienna2"

    Zmienne, tablice.

    Wszystkie zmienne są stringami.

    Nadawanie wartości "zmiennym prostym":

      set zmienna1 "qqq www eee"
      set zmienna2 {qqq www eee}
      set zmienna3 123
      set zmienna4 qwe
    
      set zmienna4
        # wynikiem tej komendy jest wartość zmiennej "zmienna4"
    
      puts "zmienna4=$zmienna4"
      puts "zmienna4=[set zmienna4]"
        # powyższe 2 linie robią, mniej więcej, to samo
    Usuwanie zmiennych:
      unset zmienna1 zmienna2
    Nadawanie wartości elementom tablic:
      set tab1(1) qqq_1
      set tab1(2) qqq_2
      set tab1(xxx) qqq_xxx
        # tablice są asocjacyjne - indeks nie musi być liczbą !
    
      puts "$tab1(xxx), $tab1(1)"
    
      parray tab1
        # procedura "parray" wypisuje elementy tablicy
    
      set indeksy_tab1 [array names tab1]
        # polecenie "array names" zwraca indeksy elementów tablicy
      foreach x $indeksy_tab1 {
        puts "tab1($x)=$tab1($x)"
      }
    UWAGA: Nie powinno się tworzyć skomplikowanych struktur danych z poziomu skryptu (gdyż języki skryptowe nie do tego są przeznaczone) !. Natomiast rozszerzenia TCL-u, pisane w języku C, mogą używać wewnętrznie skomplikowanych danych.

    Stringi, cytowanie.

    Cytowanie to wyłączanie specjalnego znaczenia niektórych znaków w stringu (tak aby interpreter ich nie interpretował, tylko traktował dosłownie).

    Cudzysłowy "" cytują słabiej, natomiast {} cytuje mocniej. Można także cytować 1 znak przy pomocy \

      set x 123
    
      puts "pwd=[pwd], \$x=$x"
        # pwd to polecenie pokazujące bieżący katalog
        # wynik: pwd=/home/faculty/mhanckow, $x=123
    
      puts {pwd=[pwd], \$x=$x}
        # wynik: pwd=[pwd], \$x=$x
    UWAGA: wydaje się, że w poniższym przykładzie mamy instrukcję sterującą, w rzeczywistości jest to zwykła komenda z czterema parametrami (które są stringami !):
      for {set i 1} {$i <= 10} {incr i} {
        puts "<<<$i>>>"
      }
    Jednak działanie tej komendy jest takie jakiego byśmy się spodziewali.

    UWAGA: w językach skryptowych często przygotowuje się "kod" w postaci stringu, a następnie ten kod jest wykonywany ja na przykładzie:

      set x1 {set i 1}
      set x2 {$i <= 10}
      set x3 {incr i}
      set x4 {puts "<<<$i>>>"}
        # trzeba użyć {}, gdyż substytucja wartości zmiennej "i"
        # ma się wykonywać dopiero w czsie działania pętli
    
      for $x1 $x2 $x3 $x4

    Listy.

    Często stringi można interpretować jako listy. Jest wiele poleceń dotyczących operacji na listach (ich nazwy zaczynają się od literki "l" !).
      info commands l*
        # wyswietla komendy, których nazwy zaczynają sie od "l"
    
      set l1 {qqq www eee rrr}
      foreach el $l1 {
        puts $el
      }
    Listy mogą być dowolnie zagnieżdżane:
      set l2 {qqq www {1 2 3 444 {q w e r} sss ddd} rrr}
    
      foreach el $l2 { puts $el }
    
      puts [lindex [lindex [lindex $l2 2] 4] 1]
        # elementy listy są numerowane od 0;
        # to polecenie powinno wyswietlic "w"

    "Instrukcje" sterujące.

      set x 10; set y 11
    
      if {$x <= $y} then {puts tak} else {puts nie}
        # w warunku nie trzeba używać "expr" !
    
      if {$x+1 <= $y+1} then {puts tak} else {puts nie}
        # priorytety operatorów w wyrażeniach:
        # patrz polecenie "expr" (podobne do j. C)
    
      if {$x+1 <= $y+1} {puts tak} {puts nie}
        # można opuszczać niektóre "słowa kluczowe"
    
      if {$x <= $y} then {
        puts tak
      } else {
        puts nie
      }     # uwaga na sposób zapisu w wielu liniach
            # nawias { MUSI byc w poprzedniej linii
    
    
      # --- petle ---
    
      set x 0
      while {$x<10} {
        puts "x is $x"
        incr x
      }
    
      for {set x 0} {$x<10} {incr x} {
        puts "x is $x"
      }
    
      set x {}
      foreach {i j} {a b c d e f} {
        lappend x $j $i
          # lappend dołącza podane elementy na koniec listy
          # ktorej nazwa jest podana przez 1 argument
      }
      # The value of x is "b a d c f e"
      # There are 3 iterations of the loop.

     

    Ważniejsze komendy TCL-u.

    expr - obliczanie wyrażeń arytmetycznych (i nie tylko)
    regexp - sprawdzanie czy napis jest zgodny z "wyrażeniem regularnym"
    info - odczytywanie rozmaitych informacji
    array - operacje na tablicach asocjacyjnych
    string - operacje na stringach
    gets/puts/open/close/read/file/glob - operacje na plikach

    Definiowanie procedur.

      proc mojaProc {param1 param2} {
        puts "$param1, $param2"
      }
    
      mojaProc 111 222
        # wywołanie procedury
    
      proc Silnia {liczba} {
        if {$liczba <= 1} then {
          return 1
        } else {
          return [expr {[Silnia [expr {$liczba-1}]] * $liczba}]
          #return [expr [Silnia [expr $liczba-1]] * $liczba]
            # tak tez dziala, ale wolniej!
        }
      }
    
    
      Silnia 10

     

    Rozszerzenie TK.

    TK służy do tworzenia "okienkowego" interfejsu użytkownika.

    Używamy interpretera "wish" lub "wish8.?". Po jego uruchomieniu pokazuje się główne okno oraz konsola, w której można wprowadzać komendy.

    Podstawowe pojęcia.

    widget
    Widgety to okienka przystosowane do konkretnego celu np do wyświetlania etykiety lub do wprowadzania napisu (w Visual Basic-u występują pod nazwa kontrolek).

    Są następujące klasy widgetów: Label, Entry, Button, Frame, Listbox, Menu, Text, Canvas, Toplevel ... i wiele innych. Konkretny widget jest obiektem danej klasy.

     
    drzewo widgetów
    Widgety tworzą drzewo widgetów. Do elementów tego drzewa odwołujemy się podobnie jak do elementów drzewa katalogów (zamiast "/" uzywamy znaku "."). Zasadniczo, podwidgety nie powinny wychodzić poza obszar swojego widgetu macierzystego.

    Sama kropka oznacza głowne okno. W poniższym przykładzie tworzymy widget klasy Label, będący podwidgetem głównego okna:

      label .l1 -text "Etykieta .l1"
    (na razie tego widgetu jeszcze nie widać, trzeba je "umieścić" !)
     
    umieszczanie widgetów
    Aby widget stał się widoczny, należy go umieścić, przy pomocy pewnego zarządcy geometrycznego. Mamy do dyspozycji kilku takich zarządców: pack, place, grid.

    Najczęściej używa sie polecenia "pack":

      pack .l1
    opcje widgetów; komenda widgetowa
    Opcja -text "..." określa jaki tekst będzie wyświetlany w widgecie ".l1". Jest bardzo wiele takich opcji; patrz man label !.

    Opcje widgetu można podać w czasie tworzenia widgetu (jak w powyższym przykładzie), Można je potem zmieniać przy pomocy komendy widgetowej. Po utworzeniu widgetu ".l1", powstaje komenda widgetowa o nazwie ".l1". Widget można konfigurować (zmieniać wartość opcji) przy pomocy podkomendy "config" komendy widgetowej;

      .l1 config -text "!!! Etykieta .l1 !!!"
    Inny przykład konfigurowania: określamy styl i grubość ramki wokół widgetu:
      .l1 config -relief raised
      .l1 config -borderwidth 0.5cm
     

    Zarządca geometryczny "pack" oraz widget "frame"

    Widget "frame" służy zasadniczo tylko do "hierarchicznego organizowanie" widgetów w drzewie widgetów:
      frame .f_a
      frame .f_b
    
      label .f_a.l1 -text "Etykieta .f_a.l1"
      label .f_a.l2 -text "Etykieta .f_a.l2"
      pack .f_a.l1 -side left
      pack .f_a.l2 -side left
    
      label .f_b.l1 -text "Etykieta .f_b.l1"
      label .f_b.l2 -text "Etykieta .f_b.l2"
      pack .f_b.l1 -side left
      pack .f_b.l2 -side left
    
      pack .f_a
      pack .f_b
    Odpowiednie opcje polecenia "pack" pozwalają sterować sposobem umieszczania podwidgetów w widgecie macierzystym. Na rysunku poniżej widać, gdzie są umieszczane widgety jeśli użyliśmy opcji "-side left" polecenia "pack" następująco:
      label .l1 -text "Etykieta .l1" -relief raised -borderwidth 0.2cm
      label .l2 -text "Etykieta .l2" -relief raised -borderwidth 0.2cm
      label .l3 -text "Etykieta .l3" -relief raised -borderwidth 0.2cm
      pack .l1 -side left
      pack .l2 -side left
      pack .l3 -side left
        # widgety będą wstawiane po lewej stronie "wydrążenia"
        # każdy widget ma swoją "parcelę"

    Gdybyśmy użyli opcji "-fill y" do polecenia "pack .l3" efekt byłby jak na rysunku poniżej (.l3 zajmie całą swoją parcelę !).

      pack .l3 -side left -fill y

    Gdybyśmy użyli opcji "-expand yes" lub "-expand 1" do polecenia "pack .l3" efekt byłby jak na rysunku poniżej (parcela .l3 zajmie całe wydrążenie !).

      pack .l3 -side left -expand yes -fill none
    
      # spróbuj także:
      pack .l3 -side left -expand yes -fill y
      pack .l3 -side left -expand yes -fill x

    UWAGA: łącząc widgety "frame" i opcje komendy "pack" można tworzyć dowolnie skomplikowane okna. Ich wzajemne rozmieszczenie jest w dużym stopniu ustalane automatycznie !.

    Widget "entry".

    Służy do wprowadzania tekstu (pojedyncza linia tekstu).
     

    Widget "button".

    Tworzy guzik, którego naciśnięcie powoduje uruchomienie skryptu podanego przez opcję "-command".
     

    Widget "scrollbar".

    Tworzy suwak; suwak ten może być w prosty sposób skojarzony z innym widgetem, np:

    Widget "listbox".

    Widget typu "listbox" zawiera listę elementów; zazwyczaj jest związany z suwakiem.
    Wstawianie elementów do listbox-u: W powyższym przykładzie słowo "end" oznacza miejsce w którym są wstawiane do listbox-u nowe elementy.  Można wstawiać w dowolne miejsce (patrz dokumentacja polecenia "listbox").
     

    Widget "text".

    Tworzy okienko pozwalające edytować tekst (w wielu liniach).
    Przykład: Komenda widgetowa "get" wymaga indeksów początku i końca tekstu, który zamierzamy odczytać; napis 1.0 to początek tekstu ("nr_linii.nr_znaku"; jak widać linie numeruje się od 1, a znaki od 0 !).

     

    Widget "canvas".

    ...............................
    ...............................
     
     

    Ważniejsze komendy TK.

    bind widget sekwencja_zdarzeń skrypt
    ...................................................
     

    Zadanie 71


    Przy pomocy widgetów "frame" i polecenia "pack", a także widgetów "label" i "entry" utwórz następujące okienko:
          Imie |---------|
      Nazwisko |---------------------|
         Adres |---------------|
             Guzik
    Symbol |---| oznacza pole do wprowadzania danych widgetu "entry"; okienka NIE muszą być wyrównane tak jak to zostało narysowane. Guzik powoduje wyświetlenie wprowadzonych napisów (patrz przykład "np02.tcl" i komenda tk_dialog).
     

    Ćwiczenie 72


    Uruchom poniższe przykłady i obejrzyj ich kod.

    Prosty przykład z guzikiem: "np02.tcl".

    Przykład "np07.tcl". Są tam tworzone 3 okienka dialogowe z formularzami. Widgety "entry" w formularzach używają tych samych zmiennych do przechowywania zawartości, dlatego gdy coś wpiszemy do w jedym okienku, to natychmiast pojawia się w pozostałych. Na tym przykładzie widać, że tworzenie okien warto wspierać procedurami !!!.

    Przykład "np16.tcl". Zastosowanie widgetów "radiobutton" i "checkbutton".

    Przykład "np19.tcl". Edycja pozycji tabeli, przy pomocy wielu okienek dialogowych.

    Przykład "np13.tcl". Program do porównywania fontów. Otwiera 3 okienka dialogowe. W każdym widać listbox z nazwami dostępnych fontów, a na dole wygląd literek ABC, w bieżącym foncie.

    Przykład "np29.tcl"+("scrolled.tcl" ). Program pokazujący dużą tablicę rysunków. Z tej tablicy widać tylko małe okienko, ze scrollbar-ami pozwalającymi je przesuwać (scrolled.tcl).

    Przykład "np26.tcl"+("scrolled.tcl" ). Program pokazuje tablicę dość złożonych elementów ("entry" ze scrollbar-em). Z tej tablicy widać tylko małe okienko, ze scrollbar-ami pozwalającymi je przesuwać (scrolled.tcl).

    Skrypt demonstracyjny "widget", który znajduje się w katalogu:

      /usr/lib/tk8.0/demos/widget
      # dotyczy Unix-a
    
      g:\app\dev\Tcl\lib\tk8.2\demos\widget.tcl
      # dotyczy WinNT
    trzeba wejść do tego katalogu  (polecenia "cd", "pwd") z poziomu konsoli, a następnie uruchomić skrypt poleceniem "source"
     

    Zadanie 73


    Napisz skrypt imitujący "Nortona Commandera", tj pozwalający chodzić po drzewie katalogów, i ewentualnie wykonywać jakieś operacje (np oglądanie zawartości pliku lub uruchamianie programów). Podstawowym widgetem, którego należy użyć, będzie oczywiście "listbox" (patrz manual lub help). Polecenie wypisujące pliki z bieżącego katalogu to "glob *", polecenia do chodzenie po drzewie katalogów to "cd" i "pwd". Przydatne będą także: "file" i "exec".
     
     
    Zadanie 74

    Zaprogramuj prosty edytor tekstu.  Powinien mieć guziki "Otwórz" do wybierania pliku (użyj polecenia tk_getOpenFile) oraz "Zapisz" do uaktualniania zmian.  Pod guzikami powinna być widoczna nazwa pliku, a pod nią zawartość pliku w widgecie "text".  Widget "text" powinien mieć pionowy i poziomy suwak.
     

    Zadanie 75 (*)


    Zaimplementuj "kulę bilardową".  Kula ta porusza się po głównym oknie i odbija się od jego ścian pod tym samym kątem pod którym w nie uderzyła.  Wszystko to ma działać w tle (jest możliwe wydawanie innych poleceń).
    Wskazówki:
    Obrazek przedstawiający kulę można pokazywać przy pomocy widgetu "label": Jednak widget ".l" musi być umieszczany przy pomocy polecenia "place" (a nie "pack"): Wysokość i szerokość widgetu ".l" można odczytać poprzez: Wysokość i szerokość głównego okna (oraz jego przesunięcie wzg ekranu) można odczytać: Wykonywanie się skryptu "w tle" można osiągnąć następująco:  
    Zadanie 76

    Skrypty "sms1.tcl" i "sms2.tcl"  pomagają przy wysyłaniu sms-ow; pierwszy skrypt wysyła sms-y bezpośrednio, drugi tworzy skrypt "ksh" ktorego uruchominie spowoduje wysłanie sms-ow. Niezbędny jest skrypt o nazwie "sms_do_XY", który faktycznie wysyła sms pobrany z stdin (desk 0). Treść smsów wprowadza się do linii o nr 1-15. Kazda linia zaczyna sie od specjalneg nagłówka "(MH??)". Gdy zostanie przekroczona długość 100 znaków jest to w pewnien sposób sygnalizowane. Do kopiowania/przenoszenia tekstu między liniami służą klawisze Ctrl-X ("Cut"), Ctrl-C ("Copy"), Ctrl-V ("Paste"). Aby się dowiedzieć w którym miejscu "złamać" linię, wystaczy cofnąc kursor.
    Co należy zrobic ? Wypróbuj te skrypty (a przynajmniej SMS2). Powiedz w jaki sposób jest sygnalizowane przekroczenie długości linii i miejsce w którym należy złamać linię. Wstaw fragment skryptu "ksh" wysylającego smsy utworzony przez SMS2. Dodaj dodatkowe okienko "entry" w ktorym podaje sie inicjaly umieszczane na poczatku każdej linii tekstu.
     

    Zadanie 77


    (Czat graficzny).
    Wypróbuj skrypty "czat4_ser.tcl" i "czat4b_kli.tcl"; są to serwer i klient usługi czat graficzny udostępniającej wspólną tablicę do rysowania oraz wspólne okienko tekstowe ("wspólne" <=> dostępne dla wielu użytkowników w sieci). Wypróbuj działanie czata graficznego uruchamiając zarówno serwer jak i klientów na lokalnej maszynie. Narysuj coś, wpisz jakiś tekst do okienka tekstowego, następnie wyłącz klientów; do sprawozdania wstaw fragment pliku "canvas.txt" w którym serwer przechowuje stan tablic (robi to na wypadek awarii).

    Standardowo usługa czat graficzny działa na lokalnej maszynie; wykonaj eksperyment w którym klienci będą się podłączać z innych komputerów (trzeba będzie zmienić pewne zmienne w skryptach klientów !).

    Pojęcia dotyczące sieci komputerowych (potrzebne aby zrozumieć działanie skryptów "czat4*.tcl") : 

    Pojęcia/ idee dotyczące Tcl/Tk:

    (koniec zadania 77)

    Zadanie 78


    (Eksperymenty z widgetem canvas).
    Napisz skrypt tworzący następujące okienko:

    Mamy tutaj następujące elementy:

    Dodaj do canvas-u jeszcze kilka elementów graficznych, o których przeczytasz w help-ie/ manualu polecenia canvas.
     

    Zadanie 78a


    (Zastosowanie canvas + elem. graf. window).
    Napisz skrypt tworzący coś w rodzaju wielkiego "arkusza kalkulacyjnego", którego fragment widzimy w małym okienku. Okienko to możemy przesuwać po arkuszu przy pomocy suwaków.
    Wskazówka: użyj widgetu canvas z elementem graficznym typu window zawierającym widget frame w którym znajduje się "arkusz" utworzony z widgetów entry + frame. Do komórek arkusza wstaw początkową wartość w postaci "wiersz X kolumna". W razie problemów patrz przykład "np29.tcl"+"scrolled.tcl" .