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)