Графичен интерфейс с Tkinter

„ Програмиране с Python“, ФМИ

['Къньо Стефанов', 'Бачий Николаев', 'Димитър Димитров']

14.05.2008

Графичен интерфейс в Python

Създаването на графичен интерфейс (GUI) е силно зависимо от операционната система - компоненти като текстови полета, бутони и менюта работят с различни механизми на Linux, Windows и Mac.

Въпреки това, в Python съществуват няколко библиотеки, които работят (горе-долу) платформено независимо.

Tkinter

Tkinter е порт на Tk за Python. Tk е мултиплатформена графична библиотека. Освен в Python, тя има имплементация в редица други езици - Tcl, Perl, Ruby.

Hello, word

from Tkinter import *
import random

def wisdom():
  return random.choice([
    "Beautiful is better than ugly.",
    "Now is better than never.",
    "Simple is better than complex.",
    "Complex is better than complicated."])

root = Tk()

greeting = Label(root, text="Hello, world!")
greeting.pack(side=TOP)

def new_wisdom():
  greeting['text'] = wisdom()

be_wise = Button(root, text="Kind sir, may I have another?", command=new_wisdom)
be_wise.pack()

root.mainloop()

Widget

Tk програмите се организират чрез дървовидна структура от компоненти. Тези компоненти се наричат Widget-и. Всеки Widget се конструира с родител и опции. Изключение правят само тези в основата на йерархията - инстанции на Tk и Toplevel. Те нямат нужда от родител.

from Tkinter import *

root = Tk()

greeting = Label(root, text="I am a label")
greeting.pack()

root.mainloop()

Опции

Всеки Widget има набор от опрции (options), които определят как изглежда. Те могат да се настройват с:

Widget(master, option1=value1, option2=value2)
widget.config(option1=value1, option2=value2)
widget['option1'] = value

Могат да се вземат с

print widget['option1']
print widget.cget('option1')

Няколко основни widget-а

Геометрии

Когато влагате компоненти един в друг, имате три алтернативи (наречени „геометрии“) за позициониране на децата.

Пример за grid()

from Tkinter import *

root = Tk()

x = Entry(root)
y = Entry(root)
result = Label(root, text="----")
logarithm = Button(root, text="log",)
exponent = Button(root, text="exp")

x.grid(row = 0, column = 0)
y.grid(row = 0, column = 1)
logarithm.grid(row = 1, column = 0)
exponent.grid(row = 1, column = 1)
result.grid(row = 2, column = 0, columnspan = 2)

root.mainloop()

mathline.py v0.2

from Tkinter import *
import math

root = Tk()

x = Entry(root)
y = Entry(root)
result = Label(root, text="----")

def do_exp():
  result['text'] = str(float(x.get()) ** float(y.get()))

def do_log():
  result['text'] = str(math.log(float(y.get()), float(x.get())))

logarithm = Button(root, text="log", command=do_log)
exponent = Button(root, text="exp", command=do_exp)

x.grid(row = 0, column = 0)
y.grid(row = 0, column = 1)
logarithm.grid(row = 1, column = 0)
exponent.grid(row = 1, column = 1)
result.grid(row = 2, column = 0, columnspan = 2)

root.mainloop()

Интерфейс за калкулатор

from Tkinter import *

class Calculator(Frame):
  def _make_button(self, name, text, row, column, columnspan=1):
    button = Button(self, text=text)
    button.grid(row = row, column = column, 
        columnspan = columnspan, sticky=W+E)
    setattr(self, name, button)

  def __init__(self, master, **kwargs):
    Frame.__init__(self, master, **kwargs)

    number = Entry(self, text="", width = 20, justify='right')
    number.grid(row = 0, column = 0, columnspan = 3, stick=W+E)

    for n in range(0, 9):
        self._make_button('button_%s' % (n+1), str(n+1), n / 3 + 1, n % 3)
    self._make_button('result', '=', 0, 4)
    self._make_button('plus', '+', 1, 4)
    self._make_button('minus', '-', 2, 4)
    self._make_button('multiply', '*', 3, 4)
    self._make_button('divide', '/', 4, 4)

    self._make_button('button_0', '0', 4, 0, 2)
    self._make_button('dot', '.', 4, 2)

root = Tk()

calc = Calculator(root)
calc.pack()

root.mainloop()

Диалогови прозорци

Може да отваряте диалогови прозорци с tkMessageBox.тиn(заглавие, съобщение, опции), като тип може да е:

tkMessageBox.showerror("Фал!", "Опа, стана фал!")

Меню

Може да създавате менюта със Menu:

from Tkinter import *

def show(text): print text

root = Tk()
menu = Menu(root)

file = Menu(menu)
file.add_command(label = "Open", command = lambda: show("Open!"))
file.add_command(label = "Save", command = lambda: show("Save!"))
file.add_separator()
file.add_command(label = "Close", command = lambda: show("Close!"))
menu.add_cascade(label = "File", menu = file)

about = Menu(menu)
about.add_command(label = "About", command = lambda: show("About!"))
menu.add_cascade(label = "Help", menu = about)

root.config(menu = menu)
root.mainloop()

Събития

Може да прихващате събития с bind(event, handler), където event е текстов низ идентифициращ събитието, а handler е едноаргументна функция, която ще бъде извикана при настъпването на събитието.

from Tkinter import *

def handle(event):
  print event.x, event.y

root = Tk()
frame = Frame(root, width=200, height=200)
frame.pack()
frame.bind("", handle)

root.mainloop()

Canvas

Canvas е widget, който позволява да чертаете свобоно. Той предлага различни методи, чертаещи различни обекти:

Canvas(2)

from Tkinter import *

root = Tk()
canvas = Canvas(root, width=300, height=300)
canvas.pack()

canvas.create_line(0, 0, 300, 300, fill='red')
canvas.create_line(0, 300, 300, 0, fill='blue')

root.mainloop()

items

Всеки начертан елемент в Canvas има уникален номер. Функциите create_* връщат този уникален номер. След това бихте могли да променяте опциите на начертания елемент чрез canvas.itemconfig(item, options) или да го триете чрез canvas.delete(item).

Етикети

Може да маркирате обектите които чертаете със текстови низове, наречени етикети. Това става като подадете опция tags, която да съдържа низ (при единичен етикет) или n-орка от низове (при няколко етикета). После може да ги намирате с canvas.find_withtag(tag).

Още въпроси?