16 HTML

Ponieważ zapoznanie się z PyGame zniechęciło mnie póki co do kontynuacji tematu, jako temat zastępczy postanowiłem zapoznać się z podstawami HTML, CSS i Bootstrap. Podstawy projektowania www to temat który zawsze chciałem zgłębić, zaczynamy:


przykład 1 - tekst i nagłówki
<!DOCTYPE html>
<html>
 <head>
  <title>
   Headings & Paragraphs
  </title>
 </head>
 <body>
  <h1>Heading - H1</h1>
  <p>Normal text</p>
  <h2>Heading - H2</h2>
  <p>Normal text</p>
  <h3>Heading - H3</h3>
  <p>Normal text</p>
  <h4>Heading - H4</h4>
  <p>Normal text</p>
  <h5>Heading - H5</h5>
  <p>Normal text</p>
  <h6>Heading - H6</h6>
  <p>Normal text</p>
 </body>
</html>


Pierwszy wiersz, <!DOCTYPE html>, definiuje typ dokumentu. Zawiera on informacje dla przeglądarki o wersji języka HTML, w którym napisany jest ten kod. W zależności od typu dokumentu przeglądarka może wyświetlać go w nieco inny sposób. W tym wypadku definiowany jest typ HTML5.

Skrót HTML oznacza hypertext markup language — hipertekstowy język znaczników. Znaczniki służą do oznaczania rodzaju treści, na przykład nagłówków, elementów list lub odnośników. Kod umieszczony wewnątrz pary znaczników może zawierać inne znaczniki HTML.

tag <head>, umieszcza się w nim różne elementy, nieco mniej istotne niż sama treść dokumentu. Na przykład tytuł, informacje pomocne dla wyszukiwarek internetowych itp.

tag <title> tytuł widoczny na zakładce przeglądarki

tag<body> treść całej strony, wszystko co wyświetla się w przeglądarce jest umieszczone tutaj

tag<p> wyświetla podany tekst

tag<h1> nagłówki h1 największy h6 najmniejszy w przykładzie



przykład 2 - linki łącza

<!DOCTYPE html>
<html>
 <head>
  <title></title>
 </head>
 <body>
     <a href="http://www.wp.pl">Wp</a>
 </body>
</html>

tag<a> znacznik łącza, zwany kotwicą, wymaga do działania dodatkowych atrybutów
hrief - hypertext reference, czyli odwołanie hipertekstowe, atrybut href wykorzystujemy w celu podania nazwy lub adresu URL, do którego prowadzi dane łącze
Pomiędzy tagiem <a> i tagiem zamykającym </a> widzimy tekst który będzie się wyświetlał jako link łącza (tutaj "Wp")



przykład 3 - linki obrazków

<!DOCTYPE html>
<html>
 <head>
  <title>Pictures</title>
 </head>
 <body>
  <img src="http://i.pinger.pl/pgr66/fd63cd870029cb9f4af49d93" />
  <img src="http://i2.pinger.pl/pgr141/15a7b00600251c8c4a1abb86/gumowa-kaczka-bob__vb__t0503025.jpg" />
 </body>
</html>

tag<img> pozwala wyświetlić nam pliki graficzne, ma atrybut src który zawiera adres URL obrazu. img podobnie jak<hr> i <br> nie ma znacznika zamykającego.

Aby wskazać plik o nazwie image.gif znajdujący się w tym samym katalogu co dokument HTML, możesz użyć poniższego znacznika:

<img src="image.gif">

Jeżeli plik obrazu znajduje się w katalogu nadrzędnym, wówczas można użyć znacznika w poniższej postaci.

<img src="../image.gif">

Zastosowanie mają dokładnie te same reguły co dla adresów URL w atrybucie href znacznika <a>.



przykład 4 link obrazu i łącza jako jedno

<!DOCTYPE html>
<html>
 <head>
  <title>Links and pictures</title>
 </head>
 <body>
  <a href="http://onet.pl"><img src="http://i.pinger.pl/pgr66/fd63cd870029cb9f4af49d93" /></a>

 </body>
</html>

Połączenie przykładu 2 i 3. W linku łącza w miejscu wyświetlanego tekstu wstawiamy...obrazek



przykład 5 listy

<!DOCTYPE html>
<html>
 <head>
  <title>O mnie</title>
 </head>
 <body>
     <h2>Moja praca</h2>
     <ol>
         <li>Dydaktyka</li>
         <li>Nauka</li>
         <li>Organizacja</li>
     </ol>
     
     <h3>Moje zainteresowania</h3>
     <ul>
         <li>Turystyka</li>
         <li>Komputery</li>
         <li>Samochody</li>
     </ul>

     <h2>A teraz wszystko razem - listy mieszane</h2>
  <ol>
   <li>Moja praca</li>
    <ul>
     <li>Dydaktyka</li>
           <li>Nauka</li>
    </ul>
   
   <li>Popularne prace
    <ul>
     <li>Kierowanie pojazdami</li>
     <li>Handel</li>
    </ul>
   </li>
  </ol>
  <ul>
      <li>Ulubione kolory</li>
          <ol>
              <li>czerwony</li>
              <li>zielony</li>
              <li>niebieski</li>
          </ol>
      <li>Inne kolory</li>
          <ol>
              <li>czarny</li>
              <li>szary</li>
              <li>granatowy</li>
          </ol>
  </ul>


 </body>
</html>

tag<ol> lista numerowana, poszczególne elementy listy za pomocą znacznika <li>
tag<ul> lista wypunktowana, elementy za pomocą <li>



przykład 6 style

<!DOCTYPE html>
<html>
 <head>
  <title>Fonts</title>
 </head>
 <body>
  <!--font-size-->
  <p></p>
  <p></p>
  <p>------------------ font-size -------------------</p>
  <p></p>
  <p style="font-size: 10px"> Some text for you to make tiny! </p>
  <p style="font-size: 20px"> Some text for you to make normal size!</p>
  <p style="font-size: 40px"> Some text for you to make super big!</p>

  <!--color-->
  <p></p>
  <p></p>
  <p>------------------ font-size and color ------------------------------------------------------------------------------------------------------------------------------------
   ++++++++++++++++++</p>
  <p></p>
  <h1 style="color: green; font-size: 16px">Big Heading</h1>
  <p style="color: violet">A giant bear and a little duck were friends.</p>
  <p style="color: red; font-size: 10px">But the bear got hungry and ate the duck.</p>

  <p></p>
  <p></p>
  <a href="http://www.w3.org/TR/css3-color/#svg-color">Link do strony z kolorami!!!</a>

  <!--font-family-->
  <p></p>
  <p></p>
  <p>------------------ font-family -----------------------------------------</p>
  <p></p>
  <h1 style="font-family: Arial">A co teraz?????</h1>
   <ol>
    <li style="font-family: Arial; font-size: 16px">This item is big Arial.</li>
    <li style="font-family: Verdana; font-size: 16px">This item is medium Verdana.</li>
    <li style="font-family: Impact; font-size: 16px">This item is small Impact.</li>
   </ol>

  <p></p>
  <p></p>
  <a href="http://www.w3.org/TR/CSS21/fonts.html#generic-font-families">A tutaj jest link do strony z fontami!!!</a>
  <p></p>
  <p></p>
  <p>------------------ text-align ------------------------------------------</p>
  <p></p>
  <h3 style="text-align: center">Favorite Football Teams</h3>
   <ol>
    <li style="text-align: left">The Hawthorn Football Club</li> 
    <li style="text-align: center">San Franscisco 49ers</li>
    <li style="text-align: right">Barcelona FC</li>
   </ol>
  <p></p>
  <p></p>
  <p></p>
  <p></p>
  <p>------------------ strong ----------------------------------------------</p>
  <p></p>
  <p>Do you hear <strong>the people sing</strong>?</p>
  <p>No I don't. I'm <strong>too</strong> busy eating cake.</p>
  <p></p>
  <p></p>
  <p></p>
  <p></p>
  <p>------------------ em --------------------------------------------------</p>
  <p></p>
  <p>Hey, don't say <em>that</em>!</p>
  <p>I am <em>so</em> tired.</p>
 </body>
</html>
 </body>
</html>

style:
style="font-size: 10px" -                     rozmiar fontów
style="color: green; font-size: 16px"  -      kolor i rozmiar fontów
style="font-family: Arial; font-size: 16px" - rodzaj fontów i ich rozmiar
style="text-align: left"                    - centrowanie tekstu
<p>Do you hear <strong>the people sing</strong>?</p> pogrubianie tekstu
<p>Hey, don't say <em>that</em>!</p>                  kursywa


przykład 7 - style kolorów

<!DOCTYPE html>
<html>
 <head>
  <title>Background-color!</title>
 </head>
 <body style="background-color: brown">
  <h3>Favorite Football Teams</h3>
   <ol style="background-color: yellow">
    <li style="background-color: blue">The Hawthorn Football Club</li> 
    <li>San Franscisco 49ers</li>
    <li>Barcelona FC</li>
   </ol>   
 </body>
</html>

Jak widać ustawiony kolor dotyczy miejsca gdzie wstawiany, body to tło, lista żółty, podpunkt listy, niebieski.




przykład 8 - tabele

<!DOCTYPE html>
<html>
    <head>
        <title>Table Time</title>
    </head>
    
    <body>
        
        <table border="1px">
            <tr>
                <th>Jeden</th><th>Dwa</th><th>Trzy</th>
            </tr>
            
            <tr>
                <td>Jeden</td><td>Dwa Trzy</td><td></td>
                
            </tr>
            
            <tr>
                <td>Jeden</td><td>Dwa</td><td>Trzy</td>
                
            </tr>
        </table>
        
    </body>

</html>

wynik:
JedenDwaTrzy
JedenDwa Trzy
JedenDwaTrzy

Wewnątrz elementu <table> ... </table> definiujesz rzeczywistą zawartość tabeli. Tbele są tworzone wiersz po wierszu, a każdy z nich zawiera wszystkie komórki dla danego wiersza. Dlatego też budowę tabeli zaczynasz od pierwszego (najwyższego) wiersza oraz jego kolejnych komórek, od lewej do prawej strony. Następnie definiujesz drugi wiersz i jego komórki itd. Liczba kolumn jest obliczana na podstawie liczby komórek znajdujących się w poszczególnych wierszach.
W przykładzie określona grubość ramek tabeli.

tag<tr> wiersz
tag<th> nagłówek wiersza- wyświetlany jako pogrubiony, rozciągniecie na 2 kolumny colspan="2"
tag<td> komórki danych czyli kolejne kolumny w wierszu


przykład 9 - tabele w stylach

<!DOCTYPE html>
<html>
    <head>
        <title>Table Time</title>
    </head>
    
    <body>
        
        <table style="border-collapse:collapse;"> <!--border-collapse: separate|collapse|initial|inherit;-->
            <thead>
                <tr style="color:red">
                    <th colspan="2">Przyklad pieknej tabeli</th>
                </tr>
                <tr style="border-bottom:1px solid black;">
                    <th style="padding:5px;"><em>naglowek 1</em></th>
                    <th style="padding:5px;border-left:1px solid black;"><em>naglowek 2</em></th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td style="padding:5px;">pierwszy</td>
                    <td style="padding:5px;border-left:1px solid black;">i opisik </td>     
                </tr>
                
                <tr>
                    <td style="padding:5px;">drugi</td>
                    <td style="padding:5px;border-left:1px solid black;">kolejny opisik</td>
                </tr>
                
                <tr>
                    <td style="padding:5px;">trzeci</td>
                    <td style="padding:5px;border-left:1px solid black;">tu tez opis</td>
                </tr>
            </tbody>
        </table>
        
    </body>

</html>

wynik:

Przyklad pieknej tabeli
naglowek 1 naglowek 2
pierwszy i opisik
drugi kolejny opisik
trzeci tu tez opis



Tą piękną tabelą kończymy wpis o podstawach HTML.





15 domowy NAS

Niedawno zakupiłem do domu mały serwer NAS firmy Synology. W tym wpisie podzielę się pierwszymi wrażeniami.



Urządzenie to Synology DS115j które umożliwiające podłączenie jednego dysku twardego.
Koszt tego urządzenia to 370zł. Cena modelu DS216se posiadającego porty na dwa dyski to 600zł.

Model droższy umożliwia ustawienie dysków w trybie RAID co gwarantuje bezpieczeństwo danych w przypadku awarii dysku. Dopłata 230zł wydawała się jednak za duża, tym bardziej, że reszta parametrów urządzeń jest taka sama (procesor 800Mhz i 256MB RAM).

Bezpieczeństwo danych postanowiłem zapewnić podłączając pendrive na usb i ustawiające regularny backup ważnych folderów realizowany przez jedną z aplikacji Synology.


Pośród wielu aplikacji dostarczanych przez producenta przetestowałem:

WebStation:

aplikację dzięki której na naszym NASie postawimy stronę www.

Jeśli posiadamy stały publiczny adres IP wystarczy na routerze nadać stały adres w sieci domowej naszemu urządzeniu NAS i przekierować port 80 na ten adres (w moim przypadku NAS w sieci domowej posiada adres 192.168.0.182 i na ten adres przekierowałem porty)

Na przykładowym zdjęciu przekierowane są dodatkowo porty:
ftp - 21
do panelu NAS - 5000
smp (samba ) - 137,138,139, 445



Teraz wystarczy wpisać nasze publiczne ip w wyszukiwarce i przykładowa strona od razu działa.
Chyba najprostszy sposób postawienia własnego serwera www. Na pewno prościej niż konfigurować Apache samemu na pc bądź raspberry pi.

FTP:
Kolejna funkcjonalność to serwer FTP, tutaj też wszystko od razu działało, jednak o ile ściąganie danych z NAS (mówimy tutaj o ściąganiu z poza domu czyli połączenie ftp z internetu poprzez nasz publiczny ip do serwera NAS) działało z szybkością domowego łącza (upload z NAS do netu) o tyle wysyłanie plików z internetu na NAS które powinno być jeszcze szybsze (domowe łącze otrzymuje dane jako download ) odbyło się z prędkością 5 razy wolniejszą niż możliwości łącza. Nie wiem czemu.

SMP
Dlatego otworzyłem porty na routerze na udostępnianie poprzez sambę (smp) czyli to co zwykle w Windows wykorzystujemy do łączności i dzielenia zasobów z drugim komputerem w sieci lokalnej:

wpisując w eksploratorze plików  \\192.168...

...co wyświetla nam udostępnione dyski, foldery drukarki innego komputera.

ewentualnie  \\192.168...\c$  jeśli żaden dysk wybranego komputera  nie jest udostępniony a chcemy dostać się do jego dysku "c"


w naszym przypadku po otwarciu portów na routerze na każdym komputerze w Internecie z Windowsem wpisujemy w oknie eksploratora plików

\\nasz.publiczny.ip

i widzimy wszystkie udostępnione foldery naszego NASa.

Teraz kopiowanie danych w obie strony odbywało się z pełną prędkością domowego łącza internetowego.
Dla fanów linuksa możemy zestawić NFS a dla Maca - AFP



Tutaj mała uwaga, domową sieć warto mieć opartą o router z wbudowanym switchem obsługującym porty 1Gb. Przepustowość takiej sieci to około 100MB na sekundę a to pozwala przesyłać dane pomiędzy komputerem a dyskiem twardym NAS'a z pełną prędkością dysku twardego czyli około 50MB/s. Jeśli chcemy korzystać z połączenia WiFi to router i komputer powinien obsługiwać standard IEEE 802.11ac  czyli 5Ghz gwarantujący 800Mb/s.

Podłączenie NAS do sieci kablowej opartej na standardzie 100Mb czyli około 10MB/s pięciokrotnie ograniczy przesył danych pomiędzy NAS a komputerem. Korzystanie z WiFi 802.11g – czyli 54 Mb/s która w praktyce przesyła 22Mb/s w jedną stronę (tylko 2,5MB/s !!!) sprawi, że komfort pracy w domu z danymi zgromadzonymi na NASie będzie tragiczny.

Temat nie dotyczy tych którzy wykorzystują NAS głównie poprzez internet, wtedy wąskim gardłem pozostaje prędkość łącza często i tak niższa niż 100Mb.


DLNA
Ponieważ posiadam telewizor ze smartTV liczyłem na możliwość odtwarzania filmów prosto z NAS'a bez konieczności ich przegrywania na dysk który podłączam do TV (przesada wiem ;-)

Faktycznie TV od razu wykrył urządzenie nadające identyfikator DLNA i pozwolił odtwarzać filmy z katalogi "video" NAS'a. Nie rozumiem tylko dlaczego nie działa opcja przewijania pilotem takiego filmu. Można jedynie za pomocą podłączonej do TV myszki wskazać na linii upływu czasu miejsce odtwarzania.



OS
Po przekierowaniu portu 5000 możemy dostać się z zewnątrz do systemu operacyjnego Synology,
gdzie po zalogowaniu możemy korzystać z zainstalowanych aplikacji. Dzięki czemu praktycznie na dowolnym obcym komputerze w internecie po połączeniu uzyskujemy dostęp do swojego środowiska i danych.



Firma Synology już w najniższych modelach udostępnia całą masę ciekawych aplikacji od businesowych (backup, office, synchronizowanie danych z chmur, radius server, zapis z kamer ip)
przez multimedialne (serwer multimediów, iTunes, audio, video )
po aplikacje dla developerów (java, apache, node.js, perl, php, python, ruby)
kończąc na narzędziach typu directory server, dns server, git server, vpn server, mail server, web server.

spis aplikacji


Nie testowałem urządzeń innych producentów ale Synology w niskiej cenie oferuje urządzenie o wysokiej funkcjonalności i przyjemności korzystania

Moje pierwsze wrażenie jest bardzo pozytywne dlatego jeśli rozważałeś zakup NAS'a polecam :-)


Konfigurowanie:

instalacja Django:

1) Podłączyć się przez terminal SSH do NAS'a  (PuTTY)
2) uzyskać uprawnienia root wpisując
    $ sudo -i
    Password: ........
3) następnie:

UPDATE For DSM 6.0 & python3.5
python3.5 -m ensurepip
python3.5 -m pip install flask
python3.5 -m pip install Django
4) można też zrobić upgrade pip:
python3.5 -m pip install --upgrade pip

5) rozpoczęcie projektu:

python3.5 -m django startproject mysite






14 GUI okienkowe II

Leksykon Widżetów:

sposób konstrukcji
w=Widget(master, option,...)
gdzie:
master - wskazanie okna rodzica (osadzenie)
option - opcje

1) Button:
b=Button(okno,opcja,...)

własności (czyli opcja)
command - funkcja wywoływana w momencie kliknęcia (callback)
justify - wyrównywanie tekstu wewnątrz  przycisku (LEFT, CENTER, RIGHT)
state - (DISABLED - dezaktywuje, NORMAL)*

* - uwaga button zdeaktywowany nie będzie wywoływał callbacka tylko jeśli został on
ustawiony poprzez polecenie command.
b=Button(okno,command=funkcjacallback)
b.place(x=0,y=0)
Jeśli powiązanie z funcją callback zostało stworzone drugą metodą czyli bind (tu reakcja na mysz)
b=Button(okno, text="przycisk")
b.place(x=0,y=0)
b.bind('<Button-1>', funkcjacallback)
to nawet zdeaktywowany button będzie reagował na kliknięcie myszy <Button-1>

metody:
flash() - migotanie przycisku
invoke() - wywołuje callbacka przypisanego do przycisku (jedyny dozwolony sposób wywołania)


2) Checkbutton - zaznaczanie ...ptaszkiem
c=Checkbutton(okno, opcja,...)

własności:
bd - szerokość ramki (domyślnie 2)
command -  callback (gdy checkbutton ZMIENIA STAN)
justify - wyrównywanie tekstu wewnątrz  przycisku (LEFT, CENTER, RIGHT)
variable - zmienna śledzona, stan widżetu( unchecked IntVar =0, checked = 1)
offvalue - domyślna wartośc wpisywana do zmiennej gdy stan unchecked
onvalue - domyślna wartośc wpisywana do zmiennej gdy stan checked
state - (DISABLED - dezaktywuje, NORMAL)*

metody:
deselect() - ustawia w stan unchecked
select() - ustawia w stan checked
flash() - mruga bez zmiany stanu
invoke() - wywołuje callbacka przypisanego
toggle() - zmienia stan widżetu na przeciwny

dla przypomnienia:

Funkcja a Metoda:

funkcja(argument)           otrzymuje argument, zwraca wynik

dana.metoda(argument)     otrzymuje argument, modyfikuje daną

czyli po stworzeniu Checkbuttona pod zmienną 'c' metodę wywołujemy:

c.flash()


przykład:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from tkinter import *
from tkinter import messagebox

def licz():
   global licznik
   licznik+=1

def pokaz():
   global c,przel,licznik
   messagebox.showinfo("","licznik="+str(licznik)+",zmienna="+str(przel.get()))


o = Tk( )
przel=IntVar()
licznik=0
b=Button(o,text="Pokaż",command=pokaz)
b.pack()
c=Checkbutton(o,text="Fifek",variable=przel,command=licz)
c.pack()
o.mainloop()



przykład użycia metody toggle()

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from tkinter import *

def przelacz():
   global c
   c.toggle()

o = Tk( )
stan=IntVar()
licznik=0
b = Button(o,text="Przelacz",command=przelacz)
b.pack()
c = Checkbutton(o,text="Fifek",variable=stan)
c.pack()
o.mainloop()


3) Radiobutton
r=Radiobutton(okno,opcja,...)

własności:
command - callback gdy zmienia stan
justify - wyrównywanie tekstu wewnątrz  przycisku (LEFT, CENTER, RIGHT)
state - (DISABLED - dezaktywuje, NORMAL)*
variable - zmienna śledzona, uwaga to przypisanie do konkretnej zmiennej grupuje przyciski !!!
wskazuje który z przycisków jest wybrany (może być IntVar albo StringVar)
value - unikalna wartość przypisana do każdego przycisku

metody:
deselect() - ustawia unchecked (żaden wybrany oznacza wyszarzona cała grupa)
flash() - kilkukrotnie mruga
invoke() - wywołuje callback
select() - ustawia checked

przykład:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from tkinter import *

def cmdr1():
    global r1,r2
    r2.set(r1.get())
def cmdr2():
    global r1,r2
    r1.set(r2.get())

o = Tk( )
r1 = IntVar()
r11 = Radiobutton(o,text="słońce",variable=r1,value=1,command=cmdr1)
r11.select()
r11.pack()
r12 = Radiobutton(o,text="deszcz",variable=r1,value=2,command=cmdr1)
r12.pack()
r2 = IntVar()
r21 = Radiobutton(o,text="północ",variable=r2,value=2,command=cmdr2)
r21.pack()
r22 = Radiobutton(o,text="połódnie",variable=r2,value=1,command=cmdr2)
r22.select()
r22.pack()
o.mainloop()


Widżety tekstowe:

Label: umieszcza tekst, nie obsługuje callbacka (command) choć może za pomocą bind
L=Label(okno, opcja)

własności:
tekst="tekst" - napis etykiety
textvariable - zmienna śledzona wyświetlana jako tekst

metody:
brak


Message: jak Label ale formatuje długi tekst
m=Message(okno,opcja)

własności:
jak Label

metody:
brak



Widżety edycyjne:

Entry: jednowierszowe pole edycyjne
e=Entry(okno, opcja,...)

określanie pozycji w polu tekstowym:
liczba - tak jak indeksowanie łańcuchów
ANCHOR - pozycja początkowa zaznaczenia
END -  pozycja końcowa zaznaczenia
INSERT - położenie kursora tekstowego

własności:
nie umożliwia dowiązania callbacka(command)
exportselection - domyślnie1, zaznaczony tekst przenoszony jest do schowka
show - znak który wyświetla podczas wpisywania np * podczas wpisywania hasła
state - (DISABLED - dezaktywuje, NORMAL)
textvariable - zmienna śledzona (StringVar) odzwierciedlająca stan pola edycji
with - szerokośc pola w znakach

metody:
delete(first,last) - kasowanie, tylko pierwszy kasuje 1 znak
get() - pobiera zawartosc pola jako tekst
icursor(index) - ustawia kursor w pozycji index
index(index,s) - wstawia do pola łańcuch s od pola index
select_clear() - usuwa zaznaczenie
select_from(index) - ustawia zaznaczenie od index
select_present() - informuje czy w polu jest aktywne zaznaczenie (True/False)
select_range(start,end) - zaznaczenie od start do end


przykład, dzięki zmiennej stowarzyszonej pozwalamy tylko na cyfry:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from tkinter import *

def tylkocyfry(*a):
    global tx,pop_s
    s = tx.get()
    if s == '' or s.isdigit():
        pop_s = s
    else:
        tx.set(pop_s)

pop_s = ''
o = Tk( )
tx = StringVar()
tc = o.register(tylkocyfry)
e = Entry(o,textvariable=tx)
tx.set(pop_s)
tx.trace('w',tylkocyfry)
e.pack()
e.focus_set()
o.mainloop()



Widżety organizacyjne:

Frame: wydziela obszar organizacyjny, ma własne współrzędne, można do niej przypinać widżety
f=Frame(okno, opcje,...)

właśności:
takefocus- pozwala ramce przyjąć skupienie jeśli ma wartość 1

przykład:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from tkinter import *

o = Tk( )
f1 = Frame(o,width=200,height=100,bg='white')
f2 = Frame(o,width=200,height=100,bg='yellow')

b11 = Button(f1,text="przycisk 1 w ramce 1")
b12 = Button(f1,text="przycisk 2 w ramce 1")
b21 = Button(f2,text="przycisk 1 w ramce 2")
b22 = Button(f2,text="przycisk 2 w ramce 2")

b11.place(x=10,y=10)
b12.place(x=10,y=50)
b21.grid(column=0,row=0)
b22.grid(column=1,row=1)

f1.pack()
f2.pack()
o.mainloop()


Menu:   menu okienka 
wybór opcji może spowodować:
-wykonanie callbacka
-rozwinięcie podmenu

utworzenie:
tworzymy obiekt menu
dowiązujemy do okna
dowiązanie podmenu (cascade) lub akcji (command) do menu głównego

m=Menu(okno, opcja,...)

własności:
postcommand - callback wywoływany gdy menu uaktywnione
tearoff - ustawione na 0 (zero) wyłącza separatory oddzierania (obecnie nieużywane)

metody:
add_cascade(coption,....) - dodaje kaskadę do menu
add_command(coption,...) - dodaje callbacka
add_separator() - dodaje separator
entryconfig(i,coption,...) - meodyfikuje właśność i-tej pozycji menu

option:
accelerator - wyświetla obok opcji klawisz skrótu (tylko wyświetla nie uruchamia go)
columnbreak - użycie wartości 1 spowoduje pojawienie się wskazanej opcji w nowej kolumnie
state - ustawiona na DISABLED uniemożliwia wybranie opcji, ACTIVE


przykład:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from tkinter import *
from tkinter import messagebox

def OAplikacji():
    messagebox.showinfo("Aplikacja","Wspaniała aplikacja,\nktóra nic nie robi")
    
okno = Tk()
# tworzymy menu główne
menuglowne = Menu(okno)
okno.config(menu=menuglowne)

# tworzymy podmenu (na razie puste)
podmenuplik = Menu(menuglowne)
menuglowne.add_cascade(label="Plik",menu=podmenuplik)

# dowiązujemy akcję do pozycji menu
podmenupomoc = Menu(menuglowne)
menuglowne.add_command(label="O aplikacji",command=OAplikacji)

okno.mainloop()


by dodać do podmenu Plik odwołanie do callbacka pytającego o zamknięcie programu:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from tkinter import *
from tkinter import messagebox

def OAplikacji():
    messagebox.showinfo("Aplikacja","Wspaniała aplikacja,\nktóra nic nie robi")

def CzyKoniec():
    global okno
    if(messagebox.askyesno("","Na pewno chcesz zakończyć pracę?")):
        okno.destroy()
        
okno = Tk()
menuglowne = Menu(okno)
okno.config(menu=menuglowne)
podmenuplik = Menu(menuglowne)
menuglowne.add_cascade(label="Plik",menu=podmenuplik,underline=0)

# dowiązujemy akcję do podmenu Plik
podmenuplik.add_command(label="Koniec",underline=0,command=CzyKoniec)

podmenupomoc = Menu(menuglowne)
menuglowne.add_command(label="O aplikacji",underline=2,command=OAplikacji)
okno.mainloop()


Jeśli chcesz się pozbyć oddzieracza z menu plik dodaj

1
podmenuplik = Menu(menuglowne,tearoff=0)

Jeśli chcemy umożliwić na korzystanie z Menu za pomocą klawiszy  - underline + index litery

1
2
# ustawiamy skrót klawiszony na Alt-P
menuglowne.add_cascade(label="Plik",menu=podmenuplik,underline=0)

By dodać do podmenu Plik kolejną pozycję np Otwórz

1
podmenuplik.add_command(label="Otwórz...",underline=0,command=Otworz)

Możesz też dodać separator w podmenu:

1
podmenuplik.add_separator()


Messagebox:
to nie widżet a klasa z metodami, metody mają trzy parametry:
tytuł - napis wyświetlany na górnej dekoracji okna
wiadomość - napis wnętrza okna \n odziela wiersze
opcje (nieobowiązkowe)
default - ustawienie odpowiedzi domyślnej: CANCEL, IGNORE, OK, NO, RETRY, YES
icon - ustawienie ikony: ERROR, INFO, QUESTION, WARNING
parent - można przypisać do innego okna niż główne

metody
askyesno(tytuł,wiadomośc,opcje) - pyta tak/nie zwraca True/False
askokcancel(tytuł,wiadomośc,opcje) - pyta ok/cancel
askretrycancel(tytuł,wiadomośc,opcje) - pyta ponów/anuluj
askquestion(tytuł,wiadomośc, opcje) - pyta tak/nie zwraca "yes" i "no"
showerror(tytuł,wiadomość, opcje) - informuje o błędzie
showinfo(tytuł,wiadomość, opcje) - pokazuje informacje
showwarning(tytuł,wiadomośc,opcje) - pokazuje ostrzeżenie



messagebox.askyesno(tytuł,wiadomość,opcje)
okienko zapyta o tak/nie, zwraca True na tak i False na nie.

przykład:

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from tkinter import *
from tkinter import messagebox

def pytanie():
    odpowiedz = messagebox.askyesno("?","Być albo nie być?")
    print(odpowiedz)
    
okno = Tk()
b = Button(okno, text="Zadaj pytanie!",command=pytanie)
b.pack()
okno.mainloop()



Kształtowanie okna głównego:


zmiana tytułu okna głównego
metoda
title()

zmiana rozmiaru okna głównego
metoda
geometry()
jej argumentem jest napis w postaci "szerokość x wysokość"

określanie minimalnej wielkości okna
metoda
minsize()

maksymalnej
metoda
maxsize()

przykład

1
2
3
4
5
6
from tkinter import *

okno = Tk()
okno.minsize(width=250, height=200)
okno.geometry("500x500")
okno.mainloop()

blokowanie wielkości okna:
metoda
resizable() - i za pomocą True False określamy które parametry blokujemy

przykład:

1
2
3
4
5
6
from tkinter import *

okno = Tk()
okno.resizable(width=False, height=True)
okno.geometry("200x200")
okno.mainloop()



Przechwytywanie zdarzenia zamknięcia okna głównego:
metoda
okno.protocol("WM_DELETE_WINDOW",callback)


13 GUI okienkowe

Tkinter

import modułu dla ułatwienia nadajemy mu skrót 'tk'

1
import tkinter as tk

możemy importować również tak

1
from tkinter import *
wtedy możemy wywoływać konstruktory bez poprzedzania ich tkinter bądź tk. (wyklucza konieczność kwalifikacji)
Poniżej będą jednak wywoływane z użyciem skrótu 'tk'.


Pierwszy konstruktor Tk, który tworzy obiekt okna głównego

1
2
3
4
import tkinter as tk

okienko=tk.Tk()
okienko.mainloop()

metoda okienko.mainloop() to uruchomienie pętli głównej (kontrolera zdarzeń)  dzięki której okienko cały czas reaguje na nasze akcje.




Nazwa okienka i przycisk Button:

Metoda title klasy Tk ustawia tytuł okna.
1
2
3
4
5
6
7
import tkinter as tk

okienko=tk.Tk()
okienko.title("Okienko")
guzik=tk.Button(okienko , text="Hej")
guzik.place(x=15, y=15)
okienko.mainloop()

konstruktor klasy Button tworzy obiekt nazwany 'guzik' reprezentujący przycisk
guzik=tk.Button(okienko , text="Hej")
pierwszym argumentem "okienko" jest nazwa obiektu okna do którego widżet będzie należeć

metoda place() klasy Button umieszcza przycisk na wskazanej pozycji (w pikselach)





Tworzenie pierwszego callbacka:

Callback to bezparametrowa funkcja wywołana przez kontroler zdarzeń po określonej akcji.

Tworzymy prosty callback 'Click'  który zapewnia sobie dostęp do globalnej zmiennej okienko i poprzez metodę destroy() zamyka okienko po czym dowiązujemy go do widżetu Button (parametr command)

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import tkinter as tk

def Click():
    global okienko
    okienko.destroy()



okienko=tk.Tk()
okienko.title("Okienko")
guzik=tk.Button(okienko , text="Hej", command=Click)
guzik.place(x=15, y=15)
okienko.mainloop()


dodatkowo możemy uzupełnić callbacka o zapytanie czy chce wyłączyć okienko. Za pomocą klasy messagebox wyświetlamy komunikat pytania. Klasa wymaga zaimportowania:

1
2
3
4
5
6
7
8
import tkinter as tk
from tkinter import messagebox

def Click():
    global okienko
    odp = tk.messagebox.askquestion("Pytanie","Jesteś pewień?")
    if odp=='yes':
        okienko.destroy()




Rozmieszczanie widżetów:

Geometry menager Tkintera oferuje 3 metody rozmieszczania widzętów w oknie

1)   place()  - z dokładnością do piksela

2)   pack() - automatycznie jeden za drugim

3)   grid() - półautomatycznie w siatce z wyrównaniem



1) place(x,y)  - (pozioma, pionowa) start w lewym górnym rogu, dodatkowo możemy dodać parametry szerokości i wysokości przycisku

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import tkinter as tk

okno=tk.Tk()

g1=tk.Button(okno, text="Guzik1")
g2=tk.Button(okno, text="Guzik2")
g3=tk.Button(okno, text="Guzik3")

g1.place(x=5,y=5,width=120)
g2.place(x=35,y=35,height=60)
g3.place(x=85,y=85,)

okno.mainloop()

wynik:


Nie potrzebujemy tworzyć zmiennych w których przechowywane są widżety jeśli dostęp do niech nie będzie później potrzebny:

1
2
3
4
5
6
7
8
9
import tkinter as tk

okno=tk.Tk()

tk.Button(okno, text="Guzik1").place(x=5,y=5,width=120)
tk.Button(okno, text="Guzik2").place(x=35,y=35,height=60)
tk.Button(okno, text="Guzik3").place(x=85,y=85,)

okno.mainloop()




2) pack(side.tk.opcje)

opcje:
TOP - ku górze okna macierzystego (Domyślne)
BOTTOM - ku dołowi
LEFT
RIGHT


3) grid(opcje_siatki)

row - rząd
column - kolumna
columnspan - liczba kolumn zajetych przez widzet
rowspan - liczba wierszy zajetych przez widżet



Zdarzenia 

Widżety które nie mają parametru command (wywołanie callbacka, przeważnie te nie klikalne) mają metodę bind.

1
widzet.bind(zdarzenie,callback)

która po określonym zdarzeniu na widżecie wywoła callbacka.

Przykładowe zdarzenia:

<Button-1> pojedyncze kliknięce lewym przyciskiem myszy
<Button-2> pojedyncze kliknięcie środkowym przyciskiem myszy (o ile jest dostępny)
<Button-3> pojedyncze kliknięcie prawym przyciskiem myszy (o ile jest dostępny)
<ButtonRelease-1> zwolnienie lewego przycisku myszy
<DoubleButton-1> podwójne kliknięcie lewego przycisku myszy
<Enter> kursor myszy pojawił się nad widżetem
<Leave> kursor myszy opuścił obszar widżetu
<Focus-In> widżet (albo jego dziecko) przejął skupienie
<Focus-Out> widżet (albo jego dziecko) stracił skupienie
<Return> użytkownik nacisnął klawisz Enter
<Key> użytkownik nacisnął jakiś klawisz
<KeyRelease> zwolnienie klawisza klawiatury

Uwaga callback dla parametru command powinien być funkcją bezparametrową, natomiast dla metody bind() powinien być funkcją z jednym parametrem. Żeby ominąć ten problem i nie pisać osobnych funkcji dopisujemy w parametrze funkcji (zdarz=None)

1
2
def clik(zdarz=None):
tk.messagebox.showinfo("Nazwa","klikasz sobie")


Można bind ale można i unbind. Istnieje też metoda bind_all oraz unbind_all.



Zmienne śledzone

Tkinter ma zestaw klas które tworzą zmienne pozwalające nadzorować zmiany ich wartości.
Niektóre z widżetów używają tych zmiennych do sygnalizowania zmiany stanu lub wpływania na ich stan.

• BooleanVar zmienna logiczna
• DoubleVar zmienna rzeczywista
• IntVar zmienna całkowita
• StringVar zmienna napisowa (łańcuchowa)

zmienną śledzoną należy utworzyć przed pierwszym użyciem

1
napisik=StringVar()



Wpisanie wartości DO zmiennej śledzonej jest możliwe tylko przez metodę set()

1
napisik.set("To właśnie przypisaliśmy")



Odczytanie wartości ZE zmiennej jest możliwe tylko przez metodę get()

1
cotamjest=napisik.get()




do istniejące zmiennej śledzonej można dodać obserwatora za pomocą metody trace()

1
obsid = zmienna.trace(tryb_śledzenia, obserwator)


do 'obsid' zostanie zapisany identyfikator obserwatora

 tryb_śledzenia to:
 "r" jeśli chcemy śledzić odczyty ze zmiennej
 "w" jeśli chcemy śledzić zapisy do zmiennej
 "u" jeśli chcemy śledzić unicestwianie zmiennej

obserwator to funkcja, która zostanie wywołana, jeśli zajdzie któreś
ze śledzonych zdarzeń
obserwator powinien być zadeklarowany jako funkcja z trzema
parametrami:

1
def obs(id,ix,act):

• id – wewnętrzny identyfikator zmiennej (nieprzydatne)
• ix – w TkInter zawsze pusty łańcuch
• act – znak informujący, jaka akcja spowodowała wywołanie
obserwatora ('r', 'w', 'u')

 jeśli żaden z tych argumentów nie jest nam potrzebny, obserwator może być zadeklarowany tak:

1
def obs(*a):