Python 12
Python 12
О графическом интерфейсе
Основы Tk
Основная черта любой программы с графическим интерфейсом -
интерактивность. Программа не просто что-то считает (в пакетном режиме) от начала
своего запуска до конца: ее действия зависят от вмешательства пользователя.
Фактически, графическое приложение выполняет бесконечный цикл обработки
событий. Программа, реализующая графический интерфейс, событийно-
ориентирована. Она ждет от интерфейса событий, которые и обрабатывает сообразно
своему внутреннему состоянию.
Классы виджетов
"<ButtonPress-3>" или просто "<3>" - щелчок правой кнопки мыши (то есть,
третьей, если считать на трехкнопочной мыши слева-направо). "<Shift-Double-
Button-1>" - двойной щелчок мышью (левой кнопкой) с нажатой кнопкой Shift. В
качестве модификаторов могут быть использованы следующие (список неполный):
Просто символ обозначает событие - нажатие клавиши. Например, "k" - тоже, что
"<KeyPress-k>". Для неалфавитно-цифровых клавиш есть специальные названия:
Здесь <space> обозначает пробел, а <less> - знак меньше. <Left>, <Right>, <Up>,
<Down> - стрелки. <Prior>, <Next> - это PageUp и PageDown. Остальные клавиши более
или менее соответствуют надписям на стандартной клавиатуре.
Примечание:
char: '\x1b'
delta: 9
height: 0
keycode: 9
keysym: 'Escape'
keysym_num: 65307
num: 9
send_event: False
serial: 159
state: 0
time: -1072960858
type: '2'
widget: <Tkinter.Text instance at 0x401e268c>
width: 0
x: 83
x_root: 448
y: 44
y_root: 306
widget.config(option=value, ...)
widget["option"] = value
value = widget["option"]
widget.keys()
В случае, когда имя свойства совпадает с ключевым словом языка Python, принято
использовать после имени одиночное подчеркивание. Так, свойство class нужно
задавать как class_, а to как to_.
При желании можно задать стилевые опции для всех виджетов сразу: с помощью
метода tk_setPalette(). Помимо использованных выше свойств в этом методе можно
использовать selectForeground и selectBackground (передний план и фон
выделения), selectColor (цвет в выбранном состоянии, например, у Checkbutton ),
insertBackground (цвет точки вставки) и некоторые другие.
Примечание:
Получить значение из поля ввода можно и при помощи метода get(). Например,
если назвать объект класса Entry именем e, получить значение можно так: e.get().
Правда, этот метод не обладает той же гибкостью, что метод get() экземпляров класса
для форматированного текста Text: можно взять только все значение целиком.
Для того чтобы показать работу с нетривиальным виджетом, можно взять виджет
ScrolledText из одноименного модуля Python. Этот виджет аналогичен рамке с
форматированным текстом и вертикальной полосой прокрутки:
tk.mainloop()
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-документ
# Первая рамка:
# Сначала две кнопки прикрепляются к левому краю
b[1, 1].pack(side=LEFT, fill=BOTH, expand=1)
b[1, 2].pack(side=LEFT, fill=BOTH, expand=1)
# Еще две - к нижнему
b[1, 3].pack(side=BOTTOM, fill=Y)
b[1, 4].pack(side=BOTTOM, fill=BOTH)
# Вторая рамка:
# Две кнопки сверху
b[2, 1].grid(row=0, column=0, sticky=NW+SE)
b[2, 2].grid(row=0, column=1, sticky=NW+SE)
# и одна на две колонки в низу
b[2, 3].grid(row=1, column=0, columnspan=2, sticky=NW+SE)
# Третья рамка:
# Кнопки высотой и шириной в 40% рамки, якорь в левом верхнем углу.
# Координаты якоря 1/10 от ширины и высоты рамки
b[3, 1].place(relx=0.1, rely=0.1, relwidth=0.4, relheight=0.4, anchor=NW)
# Кнопка строго по центру. Якорь в центре кнопки
b[3, 2].place(relx=0.5, rely=0.5, relwidth=0.4, relheight=0.4, anchor=CENTER)
# Якорь по центру кнопки. Координаты якоря 9/10 от ширины и высоты рамки
b[3, 3].place(relx=0.9, rely=0.9, relwidth=0.4, relheight=0.4, anchor=CENTER)
tk.mainloop()
Результат следующий:
Изображения в Tkinter
tk = Tkinter.Tk()
c = Tkinter.Canvas(tk, width=128, height=128)
src_img = Image.open(FILENAME)
img = ImageTk.PhotoImage(src_img)
c.create_image(0, 0, image=img, anchor="nw")
c.pack()
Tkinter.Label(tk, text=FILENAME).pack()
tk.mainloop()
В результате получается:
tk = Tk()
# Рисунок 300x300 пикселей, фон - белый
c = Canvas(tk, width=300, height=300, bg="white")
c.pack()
tk.mainloop()
tk = Tk()
c = Canvas(tk, bg="White", width="4i", height=300, relief=SUNKEN)
c.pack(expand=1, fill=BOTH)
def change_ball(event):
c.coords(CURRENT, (event.x-R, event.y-R, event.x+R, event.y+R))
c.itemconfigure(CURRENT, fill=choice(colors))
def show():
global img, imgobj
# Запрос на имя файла
filename = tkFileDialog.askopenfilename()
if filename != (): # Если имя файла было задано пользователем
# рисуется изображение из файла
src_img = Image.open(filename)
img = ImageTk.PhotoImage(src_img)
# конфигурируется изображение на рисунке
c.itemconfigure(imgobj, image=img, anchor="nw")
tk = Tk()
main_menu = Menu(tk) # формируется меню
tk.config(menu=main_menu) # меню добавляется к окну
file_menu = Menu(main_menu) # создается подменю
main_menu.add_cascade(label="File", menu=file_menu)
# Заполняется меню File
file_menu.add_command(label="Open", command=show)
file_menu.add_separator() # черта для отделения пунктов меню
file_menu.add_command(label="Exit", command=tk.destroy)
tk.mainloop()
class App(Tk):
def __init__(self):
Tk.__init__(self)
main_menu = Menu(self)
self.config(menu=main_menu)
file_menu = Menu(main_menu)
main_menu.add_cascade(label="File", menu=file_menu)
file_menu.add_command(label="Open", command=self.show_img)
file_menu.add_separator()
file_menu.add_command(label="Exit", command=self.destroy)
def show_img(self):
filename = tkFileDialog.askopenfilename()
if filename != ():
src_img = Image.open(filename)
self.img = ImageTk.PhotoImage(src_img)
self.c.itemconfigure(self.imgobj, image=self.img, anchor="nw")
app = App()
app.mainloop()
Примечание: