ЛАБОРАТОРНАЯ РАБОТА №13

Тема: Разработка графического интерфейса

Цель: Рассмотрение способов создания классов, объектов и их использования

ОГЛАВЛЕНИЕ

1 Пользовательский графический интерфейс
1.1 Создание окна
1.2 Общие свойства и методы виджетов
1.3 Системные методы
1.4 Основные виджеты
1.5 Упаковщики
1.6 Привязка событий
2 Разработка графического интерфейса
2.1 Создание окна, рамки и кнопок
2.2 Обработка событий
2.3 Работа с текстом
2.4 Использование флажков
2.5 Использование переключателей
Индивидуальные задания

 Оглавление

1 Пользовательский графический интерфейс

Графический пользовательский интерфейс GUI (Graphical User Interface) – это разновидность пользовательского интерфейса, в котором элементы интерфейса (меню, кнопки, значки, списки и т. п.), представленные пользователю на дисплее, исполнены в виде графических изображений. В отличие от интерфейса командной строки (типа старого DOS системы Windows), в GUI пользователь имеет свободный доступ ко всем элементам интерфейса экрана и может ими управлять с помощью клавиатуры или мыши.
Библиотека tkinter (от англ. Tk interface) – это встроенная графическая библиотека на основе средств Tk, широко распространенная в мире GNU/Linux и других UNIX-подобных систем, которая портирована (переведена), в частности, на Microsoft Windows и Apple Mac OS). Tk (от англ. Toolkit – «набор инструментов», «инструментарий») – кроссплатформенная библиотека базовых элементов графического интерфейса, распространяемая с открытыми исходными текстами.
Библиотека tkinter входит в стандартный дистрибутив языка Python (до версии Python 3.0 именовалась Tkinter). В tkinter стандартизированные компоненты графического интерфейса, с которыми взаимодействует пользователь, называются виджетами (widget, от англ. window gadget).

 Оглавление

1.1 Создание окна

Для подключения модуля tkinter используется форма

import tkinter from *,

позволяющая использовать все имена модуля без указания префикса tkinter.
Tk() является базовым классом любого tkinter приложения. При создании объекта этого класса запускается интерпретатор tcl/tk и создается виджетами наивысшего уровня. Обычно им является основное окно приложения. tkinter является событийно-ориентированной библиотекой. В приложениях такого типа имеется главный цикл обработки событий. В tkinter такой цикл запускается методом mainloop(). Для явного выхода из интерпретатора и завершения цикла обработки событий используется метод quit().
Таким образом минимальное приложение на Tkinter будет таким:

import tkinter from *
root = Tk()
root.mainloop()

 Оглавление

1.2 Общие свойства и методы виджетов

Все виджеты в Tkinter обладают некоторыми общими свойствами. Опишем их, перед тем как перейти к рассмотрению конкретных виджетов. Виджеты создаются вызовом конструктора соответствующего класса. Первый аргумент (как правило неименованный, но можно использовать имя master) – это родительский виджет, в который будет помещен (упакован) текущий виджет. Родительский виджет можно не указывать, в таком случае будет использовано главное окно приложения. Далее следуют именованные аргументы, конфигурирующие виджет.
Виджеты обладают следующими методами:

 Оглавление

1.3 Системные методы

Эти методы не являются виджет-специфичными, т.е. хотя они являются методами виджетов они влияют на работу интерпретатора tcl/tk:

 Оглавление

1.4 Основные виджеты

К основным виджетам можно отнести:

 Оглавление

1.5 Упаковщики

Упаковщик (менеджер геометрии, менеджер расположения) – это специальный механизм, который размещает (упаковывает) виджеты на окне. В tkinter есть три упаковщика: pack(), place() и grid(). Обратите внимание, что в одном виджете можно использовать только один тип упаковки, при смешивании разных типов упаковки программа, скорее всего, не будет работать. Разберем каждый из них по порядку:

 Оглавление

1.6 Привязка событий

Для большинства виджетов, реагирующих на действие пользователя, активацию виджета (например, нажатие кнопки) можно привязать к функции обработчику этого события, используя опцию command. К таким виджетам относятся: Button, Checkbutton, Radiobutton, Spinbox, Scrollbar, Scale. Например: button = Button(command=callback). Такой способ является предпочтительным и наиболее удобным способом привязки.
Другим способом привязки является использование метода bind(), который привязывает событие к какому-либо действию (нажатие кнопки мыши, нажатие клавиши на клавиатуре и т.д.). bind() принимает три аргумента:

Метод bind() возвращает идентификатор привязки, который может быть использован в функции unbind(). Обратите внимание, что если bind() привязан к окну верхнего уровня, то Tkinter будет обрабатывать события всех виджетов этого окна (см. также bind_all() ниже).
Функция, которая вызывается при наступлении события, должна принимать один аргумент – это объект класса Event(), в котором описано наступившее событие. Объект класса Event() имеет следующие атрибуты (в скобках указаны события, для которых этот атрибут установлен):

Эта функция может возвращать строки "continue" и "break". Если функция возвращает "continue" то Tkinter продолжит обработку других привязок этого события, если "break" - обработка этого события прекращается. Если функция ничего не возвращает (возвращает None), то обработка событий продолжается (т.е. это эквивалентно возвращению "continue").
Есть три формы названия событий. Самый простой случай это символ ASCII. Так описываются события нажатия клавиш на клавиатуре: widget.bind("z", callback). callback вызывается каждый раз, когда будет нажата клавиша "z".
Второй способ длиннее, но позволяет описать больше событий. Он имеет следующий синтаксис: <modifier-modifier-type-detail>. Название события заключено в угловые скобки. Внутри имеются ноль или более модификаторов, тип события и дополнительная информация (номер нажатой клавиши мыши или символ клавиатуры). Поля разделяются дефисом или пробелом. Приведем пример одновременного нажатия Ctrl+Shift+q: widget.bind("", callback) (в данном примере KeyPress можно убрать).
Третий способ позволяет привязывать виртуальные события - события, которые генерируются самим приложением. Такие события можно создавать самим, а потом привязывать их. Имена таких событий помещаются в двойные угловые скобки: <<Paste>>. Есть некоторое количество уже определенных виртуальных событий.
Список модификаторов:

Типы событий (здесь перечислены все возможные типы событий, для самых часто используемых дано описание):

Дополнительные методы:

Для работы с изображениями в tkinter имеется два класса – BitmapImage и PhotoImage. BitmapImage представляет собой простое двухцветное изображение, PhotoImage PhotoImage – полноцветное изображение.
Конструктор класса BitmapImageпринимает следующие аргументы:

Пример:
from Tkinter import *
data = '''#define image_width 15
#define image_height 15
static unsigned char image_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x30, 0x0c, 0x60, 0x06,
0x60, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x60, 0x06, 0x60, 0x06, 0x30, 0x0c,
0x38, 0x1c, 0x00, 0x00, 0x00, 0x00 };'''
root=Tk()
image = BitmapImage(data=data, background='red', foreground='green')
button=Button(root, image=image)
button.pack()
root.mainloop()

PhotoImage позволяет использовать полноцветное изображение. Кроме того у этого класса есть несколько (достаточно примитивных) методов для работы с изображениями. PhotoImage гарантированно понимает форматы GIF и PPM/PGM (под Windows дополнительно PNG).
Аргументы конструктора:

 Оглавление

2 Разработка приложения с использованием ООП и графического интерфейса

2.1 Создание окна, рамки и кнопок

В качестве первого примера создания пользовательского приложения с использоваением графической библиотеки tkinter рассмотрим программу gui1.py, в которой создается пользовательское окно, а в нем – рамка с тремя кнопками:

from tkinter import *
class My_frame (Frame):
''' Рамка с тремя кнопками '''
def __init__ (self,master):
super ().__init__(master)
self.grid()
self.create_widgets()
def create_widgets (self):
''' Создает три кнопки '''
self.bt1=Button(self,text= 'Кнопка №1' , fg= 'blue' , font= '12' )
self.bt1.grid()
self.bt2=Button(self)
self.bt2.grid()
self.bt2[ 'text' ]= 'Кнопка №2'
self.bt2[ 'fg' ]= 'blue'
self.bt2[ 'font' ]= '12'
self.bt3=Button(self)
self.bt3.grid()
self.bt3.config(text= 'Кнопка №3' , fg= 'blue' , font= '12' )
)

root=Tk() #Создание базового окна
root.title( 'Рамка с кнопками' )
root.geometry( '230x95+800+200' )
app=My_frame(root)
root.mainloop()

Для запуска программы gui1.py на выполнение непосредственно из лабораторной работы используется ссылка: IE:gui1.pyw. Для правильной работы ссылки необходимо:

В программе gui1.py подключение модуля tkinter осуществляется с использованием формы from tkinter import *. При этом имена всех классов и методов модуля помещаются в пространство имен программы и обращение к ним происходит без добавления префикса tkinter.
На базе класса Frame модуля tkinter создается пользовательский класс My_frame, который описывает рамку, содержащую три кнопки. При создании конструктора этого класса используется встроенная функция super(), которая предназначена для наследования методов родителького класса при их перегрузке. Таким образом, к методам конструктора класса Frame() объекта master добавляются методы: grid() – для размещения рамки, и create_widgets() – для создания кнопок в рамке.
Кнопки в виде объектов bt1, bt2 и bt3 создаются с использованием класса Button модуля tkinter. Хотя кнопки создаются в этом примере одинаковые, способы задания параметров кнопки: text – указывающего название кнопки, fg и font – задающих соответственно цвет (blue) и размеры (12 пикселей) символов, используются разные:

После описания класса в программе gui1.py:

При выполнении программы IE: gui1.pyw на экране появляется окно с заданными графическими объектами.

 Оглавление

2.2 Обработка событий

В качестве примера обработки событий, т.е. действий пользователя над виджетами, приведена программа gui2.py, в которой также, как и в программе gui1.py, создается пользовательский класс My_frame2, описывающий рамку, которая, однако, имеет следующие отличия:

from tkinter import *
class My_frame2 (Frame):
Рамка с кнопкой, подсчитывающей события '''
def __init__ (self,master):
super ().__init__(master)
self.grid()
self.bt_clicks=0
self.create_widgets()
def create_widgets (self):
''' Создает кнопку '''
self.bt1=Button(self,text= 'Число щелчков: 0' ,
command=self.count,
width= '20' ,
height= '2' ,
bg= '#efffef' ,
fg= 'blue' ,
font= 'arial 14' )
self.bt1.grid()
def count (self):
self.bt_clicks+=1
self.bt1[ 'text' ]= 'Число щелчков: ' + str (self.bt_clicks)

root=Tk()
root.title( 'Обработка событий' )
root.geometry( '240x60+800+300' )
app2=My_frame2(root)
root.mainloop()

После запуска программы IE: gui2.pyw на экране появляется окно с кнопкой, имеющей заданные параметры. После каждого щелчка мышкой по кнопке в ее наименовании число щелчков увеличивается на 1.

 Оглавление

2.3 Работа с текстом

В качестве примера работы с тестом при использовании графического интерфейса приведена программа gui3.py:

from tkinter import *
class My_frame3 (Frame):
''' Рамка для работы с текстом '''
def __init__ (self,master):
super ().__init__(master)
self.grid()
self.create_widgets()
def create_widgets (self):
''' Создает 2 метки, текстовое поле, текстовую область и кнопку '''
#метка-инструкция
self.ins_lb=Label(self, text= 'Как прожить до 100 лет?' , fg= 'blue' , font= 'arial 14' )
self.ins_lb.grid(row=0, column=0, columnspan=2,sticky=W)
#метка-пароль
self.ps_lb=Label(self, text= 'Пароль' , fg= 'blue' , font= 'arial 10' )
self.ps_lb.grid(row=1, column=0, sticky=W)
#текстовое поле для ввода пароля
self.ps_ent=Entry(self , bg= '#f0f0ff' , font= 'arial 10' )
self.ps_ent.grid(row=1, column=1, sticky=E)
#создание текстовой области, куда будет помещен ответ
self.txt=Text(self, width=30, height=4, wrap=WORD, bg= '#f0f0ff' , font= 'arial 10'' )
self.txt.grid(row=2, column=0, columnspan=2)
#кнопка отправки сообщения
self.bt=Button(self,text= 'Узнать секрет' , fg= 'blue' , bd= '5' , font= 'arial 12' ,
command=self.reveal)
self.bt.grid(row=3, column=0, sticky=W)
def reveal (self):
contents=self.ps_ent.get()
if contents== 'secret' ):
message= 'Чтобы прожить до 100 лет, надо сначала ' \
'прожить 99 лет и 11 месяцев, а потом вести себя ' \
'очень-очень осторожно.'
else :
message= 'Вы ввели неправильный пароль.'
self.secret_txt.delete(0.0,END)
self.secret_txt.insert(0.0,message)

root=Tk()
root.title( 'Работа с текстом' )
root.geometry( ''250x160+850+300' )
app3=My_frame3(root)
root.mainloop()

В программе gui3.py описан класс My_frame3, в котором с помощью метода create_widgets() создаются следующие виджеты:

Помимо метода create_widgets() в классе My_frame3 также описан обработчик щелчка по кнопке 'Узнать секрет' – метод reveal(), который:

Отметим использование в этой программе метода grid(), который осуществляет размещение (упаковку) графических элементов на рамке. В отличие от программ gui1.py и gui2.py, где метод grid() использовался без параметров и, следовательно, виджеты располагались по усматрению интерпретатора, в программе gui3.py явным образом указано расположение элементов. При использовании метода grid() поле рамки изображается в виде решетки, состоящей из рядков и колонок. Для указания местоположения виджета использованы следующие параметры:

При выполнении программы IE: gui3.pyw на экране появляется окно с описанными выше виджетами. При вводе в текстовое поле 'Пароль' неправильного пароля в текстовой области появляется сообщение "Вы ввели неправильный пароль.". А при вводе слова "secret" – появляется сообщение "Чтобы прожить до 100 лет, надо сначала прожить 99 лет и 11 месяцев, а потом вести себя очень-очень осторожно."

 Оглавление

2.4 Использование флажков

В качестве примера работы с флажками при использовании tkinter приведена программа gui4.py:

from tkinter import *
class My_frame4 (Frame):
''' Использование флажков '''
def __init__ (self,master):
super (My_frame4, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets (self):
''' Создает три флажка '''
#метка-описание
Label(self,
text= 'Укажите любимые телепередачи' , font= 'arial 13' , fg= 'blue'
).grid(row=0, column=0,sticky=W)
#метка-инструкция
Label(self,
text= 'Выберете все, что нравится' , font= 'arial 11' , fg= 'blue'
).grid(row=1, column=0,sticky=W)
#флажок 'Футбол'
self.likes_football=BooleanVar()
Checkbutton(self,text= 'Футбол' ,
variable=self.likes_football,
command=self.update_text
).grid(row=2, column=0,sticky=W)
#флажок 'История'
self.likes_history=BooleanVar()
Checkbutton(self,text= 'История' ,
variable=self.likes_history,
command=self.update_text
).grid(row=3, column=0,sticky=W)
#флажок 'Природа'
self.likes_nature=BooleanVar()
Checkbutton(self,text= 'Природа' ,
variable=self.likes_nature,
command=self.update_text
).grid(row=4, column=0,sticky=W)
#текстовая область с результатом
self.results_txt=Text(self, fg= 'blue' , font= 'arial 11' width=40, height=5, wrap=WORD)
self.results_txt.grid(row=5, column=0, columnspan=3)
def update_text (self):
likes= ''
if self.likes_football.get():
likes+= 'Вам нравится футбол\n'
if self.likes_history.get():
likes+= 'Вас привлекает история\n'
if self.likes_nature.get():
likes+= 'Вам небезразлична природа\n'
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,likes)

root=Tk()
root.title( 'Использование флажков' )
root.geometry( '270x185+800+200' )
app4=My_frame4(root)
root.mainloop()

В отличие от программ gui1.py, gui2.py и gui3.py в программе gui4.py при создании объектов меток (класс Label) используется более короткая форма – без указания имен объектов. Это допускается делать в тех случаях, когда имена этих объектов в дальнейшем не используются в описании класса.
Другой особенностью программы gui4.py является использование флажков – графических элементов класса Checkbutton, при помощи которых осуществляетя выбор (от одной до трех) телепередач:

При этом для каждого флажка:

Обработчик update_text() выполняет следующие действия:

При выполнении программы IE: gui4.pyw на экране появляется окно со следующими виджетами:

При щелчке по любому флажку в текстовую область выводится соответствующее отмеченному флажку сообщение. При повторном щелчке отметка с флажка снимается и сообщение, указанное для данного флажка, удаляется из текстовой области.

 Оглавление

2.5 Использование переключателей

В качестве примера работы с переключателями при использовании tkinter приведена программа gui5.py:

from tkinter import *
class My_frame5 (Frame):
''' Использование переключателей '''
def __init__ (self,master):
super (My_frame5, self).__init__(master)
self.grid()
self.create_widgets()
def create_widgets (self):
''' Создает переключатель '''
#метка-инструкция
Label(self,
text= 'Укажите любимую телепередачу' , fg= 'blue' , font= 'arial 13'
).grid(row=0, column=0,sticky=W)
self.favorite=StringVar()
self.favorite.set( None )
#положение переключателя 'Футбол'
Radiobutton(self,text= 'Футбол' ,
variable=self.favorite,
value= 'о футболе'
command=self.update_text
).grid(row=1, column=0,sticky=W)
#положение переключателя 'История'
Radiobutton(self,text= 'История' ,
variable=self.favorite,
value= 'об истории'
command=self.update_text
).grid(row=2, column=0,sticky=W)
#положение переключателя 'Природа'
Radiobutton(self,text= 'Природа' ,
variable=self.favorite,
value= 'о природе'
command=self.update_text
).grid(row=3, column=0,sticky=W)
#текстовая область для результата
self.results_txt=Text(self, fg= 'blue' , font= 'arial 10' , width=40, height=5, wrap=WORD)
self.results_txt.grid(row=4, column=0, columnspan=3)
def update_text (self):
message= "Ваша любимая телепередача - "
message+=self.favorite.get()
self.results_txt.delete(0.0,END)
self.results_txt.insert(0.0,message)

root=Tk()
root.title( 'Использование переключателя' )
root.geometry( '310x120+800+200' )
app=My_frame5(root)
root.mainloop()

В отличие от программы gui4.py, в которой может осуществляться выбор нескольких телепередач, в программе gui5.py можно выбрать только одну телепередачу. Поэтому вместо трех флажков класса Checkbutton используется один переключатель с тремя положениями, наименования которых соответствуют наименованиям флажков.
При этом выполняются следующие действия:

Обработчик update_text() выполняет следующие действия:

При выполнении программы IE: gui5.pyw на экране появляется окно со следующими виджетами:

При щелчке по одному из положений переключателя в текстовой области появляется соответствующее сообщение.

 Оглавление

Индивидуальные задания

Разработать программу на языке Python, в которой на базе модуля tkinter разработан графический интерфейс, имеющий несколько окон:

Таблица 1 – Перечень индивидуальных заданий

Номер
п/п
ЧислоФлажкийПереключатели
1131
2212
3323
4134
5211
6322
7133
8214
9321
10132
11213
12324
13131
14212
15323
16134
17211
18322
19133
20214

 Оглавление