keycode Код символа (скан–код клавиатуры).
keysym Символическое имя клавиши.
serial Серийный номер события. Увеличивается по мере возникновения событий.
time Время возникновения события. Все время увеличивается.
widget Виджет, в котором возникло событие.
x, y Координаты указателя в виджете во время события.
x_root, y_root Координаты указателя на экране во время события.
В принципе, совсем необязательно, чтобы события обрабатывал тот же виджет, который их первично принял. Например, можно перенаправить все события внутри подчиненных виджетов на данный виджет с помощью метода grab_set() (grab_release() освобождает виджет от этой обязанности). В Tk существуют и другие возможности управления событиями, которые можно изучить по документации.
Создание и конфигурирование виджета
Создание виджета происходит вызовом конструктора соответствующего класса. Вызов конструктора имеет следующий синтаксис:
Листинг
Widget([master[, option=value, …]])
Здесь Widget — класс виджета, master — виджет–хозяин, option и value — конфигурационная опция и ее значение (таких пар может быть несколько).
Каждый виджет имеет свойства, которые можно устанавливать (конфигурировать) с помощью методов config() (или configure()) и читать с помощью методов, подобных методам работы со словарями. Ниже приведен возможный синтаксис для работы со свойствами:
Листинг
widget.config(option=value, …)
widget[«option»] = value
value = widget[«option»]
widget.keys()
В случае, когда имя свойства совпадает с ключевым словом языка Python, принято использовать после имени одиночное подчеркивание. Так, свойство class нужно задавать как class_, а to как to_.
Изменять конфигурацию виджета можно в любой момент. Это изменение прорисуется на экране по возвращении в цикл обработки событий или при явном вызове update_idletasks().
Следующий пример показывает окно с двумя виджетами внутри — полем ввода и надписью. С помощью переменной надпись напрямую связана с полем ввода. Этот пример нарочно использует очень много свойств, чтобы продемонстрировать возможности по конфигурированию:
Листинг
from Tkinter import *
tk = Tk()
tv = StringVar()
Label(tk,
textvariable=tv,
relief=«groove»,
borderwidth=3,
font=(«Courier», 20, «bold»),
justify=LEFT,
width=50,
padx=10,
pady=20,
takefocus=False,
).pack()
Entry(tk,
textvariable=tv,
takefocus=True,
).pack()
tv.set(«123»)
tk.mainloop()
В результате на экране можно увидеть:
Виджеты конфигурируются прямо при создании. Более того, виджеты не связываются с именами, их только располагают внутри виджета–окна. В данном примере использованы свойства textvariable (текстовая переменная), relief (рельеф), borderwidth (ширина границы), justify (выравнивание), width (ширина, в знакоместах), padx и pady (прослойка в пикселях между содержимым и границами виджета), takefocus (возможность принять фокус при нажатии клавиши Tab), font (шрифт, один из способов его задания). Эти свойства достаточно типичны для многих виджетов, хотя иногда единицы измерения могут отличаться, например, для виджета Canvas ширина задается в пикселях, а не в знакоместах.
В следующем примере демонстрируются возможности по назначению цветов фону, переднему плану (тексту), выделению виджета (подсветка границы) в активном состоянии и при отсутствии фокуса:
Листинг
from Tkinter import *
tk = Tk()
tv = StringVar()
Entry(tk,
textvariable=tv,
takefocus=True,
borderwidth=10,
).pack()
mycolor1 = "#%02X%02X%02X» % (200, 200, 20)
Entry(tk,
textvariable=tv,
takefocus=True,
borderwidth=10,
foreground=mycolor1, # fg, текст виджета
background="#0000FF», # bg, фон виджета
highlightcolor='green', # подсветка при фокусе
highlightbackground='red', # подсветка без фокуса
).pack()
tv.set(«123»)
tk.mainloop()
При желании можно задать стилевые опции для всех виджетов сразу: с помощью метода tk_setPalette(). Помимо использованных выше свойств в этом методе можно использовать selectForeground и selectBackground (передний план и фон выделения), selectColor (цвет в выбранном состоянии, например, у Checkbutton), insertBackground (цвет точки вставки) и некоторые другие.
Примечание:
Получить значение из поля ввода можно и при помощи метода get(). Например, если назвать объект класса Entry именем e, получить значение можно так: e.get(). Правда, этот метод не обладает той же гибкостью, что метод get() экземпляров класса для форматированного текста Text: можно взять только все значение целиком.
Виджет форматированного текста
Для того чтобы показать работу с нетривиальным виджетом, можно взять виджет ScrolledText из одноименного модуля Python. Этот виджет аналогичен рамке с форматированным текстом и вертикальной полосой прокрутки:
Листинг
from Tkinter import *
from ScrolledText import ScrolledText
tk = Tk() # окно верхнего уровня
txt = ScrolledText(tk) # виджет текста с прокруткой
txt.pack() # виджет размещается
for x in range(1, 1024): # виджет наполняется текстовым содержимым
txt.insert(END, str(2L**x)+»\n»)
tk.mainloop()
Теперь следует рассмотреть методы и свойства виджета с форматированным текстом более подробно.
Для навигации в тексте в Tk предусмотрены специальные индексы. Индексы вроде 1.0 и END уже встречались — это начало текста (первая строка, нулевой символ) и его конец. (В Tk строки нумеруются с единицы, а символы строки — с нуля). Более полный список индексов:
L.C Здесь L — номер строки, а C — номер символа в строке.
INSERT Точка вставки.
CURRENT Символ, ближайший к курсору мыши.
END Позиция сразу за последним символом в тексте
M.first, M.last Индексы начала и конца помеченного тегом M участка текста.
SEL_FIRST, SEL_LAST Индексы начала и конца выделенного текста.
M Пользователь может определять свои именованные позиции в тексте (аналогично END, INSERT или CURRENT). При редактировании текста маркеры будут сдвигаться с заданными для них правилами.
@x,y Символ текста, ближайший к точке с координатами x, y.
Следующий пример показывает, как снабдить форматированный текст гипертекстовыми возможностями:
Листинг
from Tkinter import *
import urllib
tk = Tk()
txt = Text(tk, width=64) # поле с текстом
txt.grid(row=0, column=0, rowspan=2)
addr=Text(tk, background=«White», width=64, height=1) # поле адреса
addr.grid(row=0, column=1)
page=Text(tk, background=«White», width=64) # поле с html–кодом
page.grid(row=1, column=1)
def fetch_url(event):
click_point = "@%s,%s» % (event.x, event.y)
trs = txt.tag_ranges(«href») # список областей текста, отмеченных как href
url = ""
# определяется, на какой участок пришелся щелчок мыши, и берется
# соответствующий ему URL
for i in range(0, len(trs), 2):
if txt.compare(trs[i], "<=", click_point) and \
txt.compare(click_point, "<=", trs[i+1]):
url = txt.get(trs[i], trs[i+1])
html_doc = urllib.urlopen(url).read()
addr.delete(«1.0», END)
addr.insert(«1.0», url) # URL помещается в поле адреса
page.delete(«1.0», END)
page.insert(«1.0», html_doc) # показывается HTML–документ
textfrags = [«Python main site: ", «http://www.python.org»,
«\nJython site: ", «http://www.jython.org»,
«\nThat is all!»]
for frag in textfrags:
if frag.startswith(«http:"):
txt.insert(END, frag, «href») # URL помещается в текст с меткой href