Tkinter


Entry Widget

Entry Fields on Wall
Widgety Entry jsou základní objekty Tkinteru pro vkládání vstupních údajů od uživatele, například řetězců. Tento widget umožní zadat jeden řádek textu. Zadá-li uživatel řetězec, který je delší než vymezené místo ve widgetu, je viditelná pouze jeho část. Ke zviditelnění zakrytých částí lze použít klávesnice se šipkami. Potřebujeme-li zadat víceřádkový text, použijeme widget Text.

Deklarace objektu Entry vypadá takto:

w = Entry(master, option, ... )

Parametr "master" představuje rodičovské okno, ve kterém má být widget "entry" umístěn. Stejně jako u ostatních widgetů je možné dále ovlivnit vzhled widgetu použitím parametrů.

Následující příklad vytváří aplikaci se dvěma vstupními poli. Jedno pro zadání křestního jména, druhé pro zadání příjmení.

from tkinter import *

master = Tk()
Label(master, text="First Name").grid(row=0)
Label(master, text="Last Name").grid(row=1)

e1 = Entry(master)
e2 = Entry(master)

e1.grid(row=0, column=1)
e2.grid(row=1, column=1)

mainloop( )
Okno, vytvořené předcházejícím skriptem, vypadá takto:

Entry Fields for names



Nuže, vytvořili jsme vstupní pole, do nichž může uživatel vkládat nějaká data. Jak se ale program k těmto datům dostane, jak přečte obsah vstupních polí?

Jednoduše - použijeme metodu get(). Rozšíříme náš malý skript o dvě tlačítka "Quit" a "Show". Propojíme funkci show_entry_fields(), která používá metodu get() pro objekty Entry, s tlačítkem Show. Při každém poklepu tohoto tlačítka se obsah vstupního pole vytiskne na terminálu, ze kterého byl skript spuštěn.
from tkinter import *

def show_entry_fields():
    print("First Name: %s\nLast Name: %s" % (e1.get(), e2.get()))

master = Tk()
Label(master, text="First Name").grid(row=0)
Label(master, text="Last Name").grid(row=1)

e1 = Entry(master)
e2 = Entry(master)

e1.grid(row=0, column=1)
e2.grid(row=1, column=1)

Button(master, text='Quit', command=master.quit)
        .grid(row=3, column=0, sticky=W, pady=4)
Button(master, text='Show', command=show_entry_fields)
        .grid(row=3, column=1, sticky=W, pady=4)

mainloop( )

Kompletní výsledek vypadá takto:

Entry Fields for names plus Show and quit button

Předpokládejme nyní, že chceme spouštět aplikaci s přednastavenými hodnotami (např. Jill Miller) ve vstupních polích. Nová verze našeho programu dostane následující dva řádky, které mohou být přidány za definicemi vstupních polí (e2 = Entry(master)):

e1.insert(10,"Jill")
e2.insert(10,"Miller")

Což takhle smazávat obsah vstupního pole po každém jeho zobrazení v terminálu? Žádný problém. Použijeme metodu delete(). Tato metoda má formát delete(first, last=None). Je-li zadáno pouze jedno číslo, je považováno za index a smaže se odpovídající alfanumerický znak. Jsou-li zadána dvě čísla, tvoří hranice rozsahu (range) a vymaže se odpovídající rozsah znaků. Pro vymazávání veškerého textu zadáváme delete(0, END).

from tkinter import *

def show_entry_fields():
    print("First Name: %s\nLast Name: %s" 
    	   % (e1.get(), e2.get()))
    e1.delete(0,END)
    e2.delete(0,END)

master = Tk()
Label(master, text="First Name").grid(row=0)
Label(master, text="Last Name").grid(row=1)

e1 = Entry(master)
e2 = Entry(master)
e1.insert(10,"Miller")
e2.insert(10,"Jill")

e1.grid(row=0, column=1)
e2.grid(row=1, column=1)

Button(master, text='Quit', command=master.quit)
       .grid(row=3, column=0, sticky=W, pady=4)
Button(master, text='Show', command=show_entry_fields)
       .grid(row=3, column=1, sticky=W, pady=4)

mainloop( )

Další příklad ukazuje, jak můžeme elegantně vytvářed řadu vstupních polí více pythonovským způsobem. Pro jejich popis použijeme seznam Pythonu, který do aplikace vložíme jako popisky.
from tkinter import *

fields = 'Last Name', 'First Name', 'Job', 'Country'

def fetch(entries):
    for entry in entries:
        field = entry[0]
        text  = entry[1].get()
        print('%s: "%s"' % (field, text)) 

def makeform(root, fields):
    entries = []
    for field in fields:
        row = Frame(root)
        lab = Label(row, width=15, text=field, anchor='w')
        ent = Entry(row)
        row.pack(side=TOP, fill=X, padx=5, pady=5)
        lab.pack(side=LEFT)
        ent.pack(side=RIGHT, expand=YES, fill=X)
        entries.append((field, ent))
    return entries

if __name__ == '__main__':
    root = Tk()
    ents = makeform(root, fields)
    root.bind('<Return>', (lambda event, e=ents:
            	           fetch(e)))   
    b1 = Button(root, text='Show', 
                command=(lambda e=ents: fetch(e)))
    b1.pack(side=LEFT, padx=5, pady=5)
    b2 = Button(root, text='Quit', command=root.quit)
    b2.pack(side=LEFT, padx=5, pady=5)
    root.mainloop()

Spuštěný skript vypadá takto:

Name and Job: Bernd Klein, Lecturer, Germany

Kalkulátor

Úplný kalkulátor nevytvoříme ale sestavíme GUI, ve kterém lze matematický výpočet provést a výsledek vytisknout.
from tkinter import *
from math import *

def evaluate(event):
    res.configure(text = "Ergebnis: " + 
        	  str(eval(entry.get())))

w = Tk()
Label(w, text="Your Expression:").pack()
entry = Entry(w)
entry.bind("<Return>", evaluate)
entry.pack()
res = Label(w)
res.pack()

w.mainloop()


Naše aplikace vypadá takto:

Expression evaluation in Python and Tkinter

Výpočet úroku

Následující vzorec lze použít k výpočtu zůstatku Bk po provedených k platbách, počínaje počáteční hodnotou půjčky Bo a úrokovou mírou r:

Formula: calculating the monthly payment of a Loan to be paid of in n payment.
kde
rate = roční úroková míra v procentech, např. 3 %
i = rate / 100, roční úroková míra v decimální formě
r = úroková míra období = i / 12
B0 = hodnota půjčky (loan principle)
Bk = výše dluhu po k platbách
k = počet měsíčních splátek
p = měsíční splátka (monthly payment)
Chceme-li určit nezbytnou měsíční splátku, má-li být půjčka splacena v zadaných n splátkách, nastavíme Bn = 0 a dostaneme vzorec:

Formula: calculating the monthly payment of a Loan to be paid of in n payment.
kde
n = počet měsíčních splátek

from tkinter import *

fields = ('Annual Rate', 'Number of Payments',
          'Loan Principle', 'Monthly Payment',
          'Remaining Loan')

def monthly_payment(entries):
    # period rate:
    r = (float(entries['Annual Rate'].get()) / 100) / 12
    print("r", r)
    # principal loan:
    loan = float(entries['Loan Principle'].get())
    n =  float(entries['Number of Payments'].get())
    remaining_loan = float(entries['Remaining Loan']
	                   .get())
    q = (1 + r)** n
    monthly = r*( (q*loan - remaining_loan) / ( q - 1 ))
    monthly = ("%8.2f" % monthly).strip()
    entries['Monthly Payment'].delete(0,END)
    entries['Monthly Payment'].insert(0, monthly )
    print("Monthly Payment: %f" % monthly)

def final_balance(entries):
    # period rate:
    r = (float(entries['Annual Rate'].get()) / 100) / 12
    print("r", r)
    # principal loan:
    loan = float(entries['Loan Principle'].get())
    n =  float(entries['Number of Payments'].get()) 
    q = (1 + r)** n
    monthly = float(entries['Monthly Payment'].get())
    q = (1 + r)** n
    remaining = q * loan  - ( (q - 1) / r) * monthly
    remaining = ("%8.2f" % remaining).strip()
    entries['Remaining Loan'].delete(0,END)
    entries['Remaining Loan'].insert(0, remaining )
    print("Remaining Loan: %f" % remaining)

def makeform(root, fields):
    entries = {}
    for field in fields:
        row = Frame(root)
        lab = Label(row, width=22, text=field+": ",
        	    anchor='w')
        ent = Entry(row)
        ent.insert(0,"0")
        row.pack(side=TOP, fill=X, padx=5, pady=5)
        lab.pack(side=LEFT)
        ent.pack(side=RIGHT, expand=YES, fill=X)
        entries[field] = ent
    return entries

if __name__ == '__main__':
    root = Tk()
    ents = makeform(root, fields)
    root.bind('<Return>', (lambda event, e=ents:
                     	   fetch(e)))   
    b1 = Button(root, text='Final Balance',
            command=(lambda e=ents: final_balance(e)))
    b1.pack(side=LEFT, padx=5, pady=5)
    b2 = Button(root, text='Monthly Payment',
            command=(lambda e=ents: monthly_payment(e)))
    b2.pack(side=LEFT, padx=5, pady=5)
    b3 = Button(root, text='Quit', command=root.quit)
    b3.pack(side=LEFT, padx=5, pady=5)
	
    root.mainloop()


Náš úrokový kalkulátor vypadá následovně, pokud je spustíme v Pythonu3:

Loan calculator in Python and Tkinter