Работа с графическим интерфейсом
Выбери формат для чтения
Загружаем конспект в формате pdf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Основы алгоритмизации и
программирование
Лекции 22-25.
Tkinter. Работа с графическим интерфейсом.
Импорт модуля tkinter
from tkinter import *
Python 3 — tkinter
Python 2 — Tkinter
2
Создание главного окна
root = Tk()
…
root.mainloop()
3
Виджеты
переменная = Button (родит_виджет,
[свойство=значение, … ….])
def printer(event):
print ("World!")
but = Button(root)
but["text"] = "Печать"
but.bind("",printer)
but.pack()
root.mainloop()
4
Кнопка. Button.
from tkinter import *
root = Tk()
but = Button(root,
text="Это кнопка", #надпись на кнопке
width=30,height=5, #ширина и высота
bg="white",fg="blue") #цвет фона и надписи
but.pack()
root.mainloop()
5
Метка. Label.
lab = Label(root, text="Это метка! \n Из двух строк.", font="Arial 18")
6
Однострочное текстовое поле. Entry.
ent = Entry(root,width=20,bd=3)
Для многих виджетов работает метод get().
7
Многострочное текстовое поле. Text.
tex = Text(root,width=40, font="Verdana 12", wrap=WORD)
8
Радиокнопки. Radiobutton.
var=IntVar()
var.set(0)
rad0 = Radiobutton(root,text="Первая",
variable=var,value=0)
rad1 = Radiobutton(root,text="Вторая",
variable=var,value=1)
rad2 = Radiobutton(root,text="Третья",
variable=var,value=2)
Массив радиокнопок. Например, так:
var=IntVar()
var.set(0)
r = ['Linux','Python','Tk','Tkinter']
rad=[]
i=0
while i",output)
root.mainloop()
16
Пример
li = ["red","green"]
def color(event):
fra.configure(bg=li[0])
li[0],li[1] = li[1],li[0]
def outgo(event):
root.destroy()
from tkinter import *
root = Tk()
fra = Frame(root,width=100,height=100)
but = Button(root,text="Выход")
fra.pack()
but.pack()
root.bind("",color)
but.bind("",outgo)
root.mainloop()
17
События, производимые мышью
- щелчок левой кнопкой мыши
- щелчок средней кнопкой мыши
- щелчок правой кнопкой мыши
- двойной клик левой кнопкой
мыши
- движение мыши
18
Пример
from tkinter import *
def b1(event):
root.title("Левая кнопка мыши")
def b3(event):
root.title("Правая кнопка мыши")
def move(event):
root.title("Движение мышью")
root = Tk()
root.minsize(width = 500, height=400)
root.bind('',b1)
root.bind('',b3)
root.bind('',move)
root.mainloop()
19
События, производимые с помощью клавиатуры
Буквенные клавиши можно записывать
без угловых скобок (например, 'L'). Для
неалфавитных клавиш существуют
специальные зарезервированные слова
- нажатие клавиши Enter;
- пробел;
и т. д.
20
Пример
from tkinter import *
def printer(event):
print ("Как всегда очередной
'Hello World!'")
root = Tk()
root.bind('',printer)
root.mainloop()
21
Пример
from tkinter import *
def exit_(event):
root.destroy()
def caption(event):
t = ent.get()
lbl.configure(text = t)
root = Tk()
ent = Entry(root, width = 40)
lbl = Label(root, width = 80)
ent.pack()
lbl.pack()
ent.bind('',caption)
root.bind('',exit_)
root.mainloop()
22
Вычисление числа Фибоначчи (GUI):
from tkinter import *
fibs={1:0, 2:1}
def fib(x):
if x in fibs:
return fibs[x]
fibs[x]=fib(x-1)+fib(x-2)
return fibs[x]
def compute(event):
lab['text']=fib(int(ent.get()))
root=Tk()
but=Button(root,
text='Вычислить',
bg='brown')
lab = Label(root)
ent = Entry(root,width=20,bd=3)
ent.pack()
lab.pack()
but.pack()
but.bind("",compute)
root.mainloop()
23
Grid
from tkinter import *
fibs={1:0, 2:1}
def fib(x):
if x in fibs:
return fibs[x]
fibs[x]=fib(x-1)+fib(x-2)
return fibs[x]
def compute(event):
lab['text']=fib(int(ent.get()))
root=Tk()
but=Button(root,
text='Вычислить',
bg='brown',width=20)
exbut=Button(root,
text='Выход',
bg='red', command=root.destroy,width=20)
but.bind("",compute)
lab = Label(root,width=20)
ent = Entry(root,width=20,bd=3)
ent.grid(row=0, column=0)
lab.grid(row=0, column=1)
but.grid(row=2,column=0)
exbut.grid(row=2,column=1)
root.mainloop()
24
Переменные Tkinter
StringVar() –для строк;
IntVar() – целых чисел;
DoubleVar() – дробных чисел;
BooleanVar() – для обработки булевых значений (true и false).
var=IntVar()
var.set(1)
rad0 = Radiobutton(root,text="Первая",variable=var,value=0)
rad1 = Radiobutton(root,text="Вторая",variable=var,value=1)
rad2 = Radiobutton(root,text="Третья",variable=var,value=2)
v = var.get()
25
Для флажков
var0=StringVar()
var1=StringVar()
var2=StringVar()
ch0 = Checkbutton(root,text="Окружность",variable=var0,
onvalue="circle",offvalue="-")
ch1 = Checkbutton(root,text="Квадрат",variable=var1,
onvalue="square",offvalue="-")
ch2 = Checkbutton(root,text="Треугольник",variable=var2,
onvalue="triangle",offvalue="-")
from tkinter import *
root = Tk()
var0=StringVar() # значение каждого флажка ...
var1=StringVar() # ... хранится в собственной переменной
var2=StringVar()
# если флажок установлен, то в ассоциированную переменную ...
# ...(var0,var1 или var2) заносится значение onvalue, ...
# ...если флажок снят, то - offvalue.
ch0 = Checkbutton(root,text="Окружность",variable=var0,
onvalue="circle",offvalue="-")
ch1 = Checkbutton(root,text="Квадрат",variable=var1,
onvalue="square",offvalue="-")
ch2 = Checkbutton(root,text="Треугольник",variable=var2,
onvalue="triangle",offvalue="-")
lis = Listbox(root,height=3)
def result(event):
v0 = var0.get()
v1 = var1.get()
v2 = var2.get()
l = [v0,v1,v2] # значения переменных заносятся в список
lis.delete(0,2) # предыдущее содержимое удаляется из Listbox
for v in l: # содержимое списка l последовательно ...
lis.insert(END,v) # ...вставляется в Listbox
but = Button(root,text="Получить значения")
but.bind('',result)
ch0.deselect()# "по умолчанию" флажки сняты
ch1.deselect()
ch2.deselect()
ch0.pack()
ch1.pack()
ch2.pack()
but.pack()
lis.pack()
root.mainloop()
26
Textvariable
from tkinter import *
root = Tk()
v = StringVar()
ent1 = Entry (root, textvariable =
v,bg="black",fg="white")
lab2 = Label(root, textvariable = v)
ent1.pack()
ent2.pack()
root.mainloop()
27
Меню
from tkinter import *
root = Tk()
m = Menu(root) #создается объект Меню на главном окне
root.config(menu=m) #окно конфигурируется с указанием меню для него
fm = Menu(m) #создается пункт меню с размещением на основном меню (m)
m.add_cascade(label="File",menu=fm) #пункту располагается на основном меню (m)
fm.add_command(label="Open...") #формируется список команд пункта меню
fm.add_command(label="New")
fm.add_command(label="Save...")
fm.add_command(label="Exit")
hm = Menu(m) #второй пункт меню
m.add_cascade(label="Help",menu=hm)
hm.add_command(label="Help")
hm.add_command(label="About")
root.mainloop()
28
Вложенное меню
nfm = Menu(fm)
fm.add_cascade(label="Import",menu=nfm)
nfm.add_command(label="Image")
nfm.add_command(label="Text")
29
Привязка функций к меню
def new_win():
win = Toplevel(root)
def close_win():
root.destroy()
def about():
win = Toplevel(root)
lab = Label(win,text="Это просто программа-тест \n меню в Tkinter")
lab.pack()
….
fm.add_command(label="New",command=new_win)
….
fm.add_command(label="Exit",command=close_win)
….
hm.add_command(label="About",command=about)
30
Диалоговые окна
from tkinter import *
from tkinter.filedialog import *
root = Tk()
op = askopenfilename()
sa = asksaveasfilename()
root.mainloop()
31
Открытие текстового файла
from tkinter import *
from tkinter.filedialog import *
root = Tk()
txt =
Text(root,width=40,height=15,font="12")
txt.pack()
op = askopenfilename()
txt.insert(END,op)
root.mainloop()
.....
import fileinput
.....
for i in fileinput.input(op):
txt.insert(END,i)
32
Открытие файла через меню
from tkinter import *
from tkinter.filedialog import *
import fileinput
def open():
op = askopenfilename()
for l in fileinput.input(op):
txt.insert(END,l)
root = Tk()
m = Menu(root)
root.config(menu=m)
fm = Menu(m)
m.add_cascade(label="File",menu=fm)
fm.add_command(label="Open...",command=_open)
txt = Text(root,width=40,height=15,font="12")
txt.pack()
root.mainloop()
txt.delete(1.0, END)
33
Сохранение
def save():
sa = asksaveasfilename()
letter = txt.get(1.0,END)
f = open(sa,"w")
f.write(letter)
f.close()
fm.add_command(label="Save as",command=save)
Ошибка из-за наличия внутренней функции open
34
Messagebox
from tkinter.messagebox import *
….
def close_win():
if askyesno("Exit", "Do you want to quit?"):
root.destroy()
def about():
showinfo("Editor", "This is text editor.\n(test version)")
...
fm.add_command(label="Exit",command=close_win)
....
hm = Menu(m)
m.add_cascade(label="Help",menu=hm)
hm.add_command(label="About",command=about)
35
Полный текст программы:
from tkinter import *
from tkinter.filedialog import *
import fileinput
from tkinter.messagebox import *
def close_win():
if askyesno("Exit", "Do you want to quit?"):
root.destroy()
def about():
showinfo("Editor", "This is text editor.\n(test version)")
def save():
sa = asksaveasfilename()
letter = txt.get(1.0,END)
f = open(sa,"w")
f.write(letter)
f.close()
def fopen():
op = askopenfilename()
txt.delete(1.0, END)
for l in fileinput.input(op):
txt.insert(END,l)
root = Tk()
m = Menu(root)
root.config(menu=m)
fm = Menu(m)
m.add_cascade(label="File",menu=fm)
fm.add_command(label="Open...",command=fopen)
fm.add_command(label="Save as",command=save)
fm.add_command(label="Exit",command=close_win)
hm = Menu(m)
m.add_cascade(label="Help",menu=hm)
hm.add_command(label="About",command=about)
txt = Text(root,width=40,height=15,font="12")
txt.pack()
root.mainloop()
36
Canvas
canv = Canvas(root,width=500,height=500,bg="lightblue",
cursor="pencil")
37
Линии и фигуры
canv.create_line(200,50,300,50,width=3,fill="blue")
canv.create_line(0,0,100,100,width=2,arrow=LAST)
x = 75
y = 110
canv.create_rectangle(x,y,x+80,y+50,fill="white",outline="blue")
canv.create_polygon([250,100],[200,150],[300,150],fill="yellow")
canv.create_polygon([300,80],[400,80],[450,75],[450,200],
[300,180],[330,160],outline="white",smooth=1)
38
Круги и их части
canv.create_arc([160,230],[230,330],start=0,extent=140,fill="lightgreen")
canv.create_arc([250,230],[320,330],start=0,extent=140,
style=CHORD,fill="green")
canv.create_arc([340,230],[410,330],start=0,extent=140,
style=ARC,outline="darkgreen",width=2)
canv.create_oval(0,0,130,80)
39
Надписи и циклы
canv.create_text(20,330,text="Опыты с графическими примитивами\nна
холсте",
font="Verdana 12",anchor="w",justify=CENTER,fill="red")
x=10
while x < 450:
canv.create_rectangle(x,400,x+50,450)
x = x + 60
40
Идентификаторы элементов холста
c = Canvas(width=460,height=460,bg='grey80')
c.pack()
oval = c.create_oval(30,10,130,80)
rect = c.create_rectangle(180,10,280,80)
trian = c.create_polygon(330,80,380,10,430,80, fill='grey80', outline="black")
c.move(rect,0,150)
c.itemconfig(trian,outline="red",width=3)
c.coords(oval,300,200,450,450)
41
Теги элементов холста
oval = c.create_oval(30,10,130,80,tag="group1")
c.create_line(10,100,450,100,tag="group1")
…
def color(event):
c.itemconfig('group1',fill="red",width=3)
…
c.bind('',color)
42
Удаление элементов холста
def clean(event):
c.delete('all')
...
c.bind('',clean)
43
Метод tag_bind
from tkinter import *
c = Canvas(width=460,height=100,bg='grey80')
c.pack()
oval = c.create_oval(30,10,130,80,fill="orange")
c.create_rectangle(180,10,280,80,tag="rect",fill="lightgreen")
trian = c.create_polygon(330,80,380,10,430,80,fill='white',outline="black")
def oval_func(event):
c.delete(oval)
c.create_text(30,10,text="Здесь был круг",anchor="w")
def rect_func(event):
c.delete("rect")
c.create_text(180,10,text="Здесь был\nпрямоугольник",anchor="nw")
def triangle(event):
c.create_polygon(350,70,380,20,410,70,fill='yellow',outline="black")
c.tag_bind(oval,'',oval_func)
c.tag_bind("rect",'',rect_func)
c.tag_bind(trian,'',triangle)
mainloop()
44
Рисование кистью
from tkinter import *
def draw(event):
canvas.create_oval(event.x-2,
event.y-2,event.x+2,event.y+2,fill='blue')
def clear(event):
canvas.create_oval(event.x-10, event.y10,event.x+10,event.y+10,fill='white',outli
ne='white')
С помощью
event.widget мы
можем обращаться
к виджету,
который вызвал
событие.
canvas=Canvas(bg='white',cursor='pencil')
canvas.pack()
canvas.bind('', draw)
canvas.bind('', clear)
45
Сохранение и открытие изображений
from tkinter import *
from PIL import Image, ImageTk, ImageGrab
def saveimg(event):
x1=canvas.winfo_rootx()
x2=canvas.winfo_rootx()+300
y1=canvas.winfo_rooty()
y2=canvas.winfo_rooty()+300
ImageGrab.grab((x1,y1,x2,y2)).save('res.jpg')
root = Tk()
canvas = Canvas(root,width=300,height=300)
canvas.pack()
pilImage = Image.open("1.jpg")
image = ImageTk.PhotoImage(pilImage)
img =
canvas.create_image(150,150,image=image)
b1=Button(root,width=10,text='Save')
b1.bind('<1>',saveimg)
b1.pack()
root.mainloop()
46
Особенности работы с виджетом Text
from tkinter import *
tx = Text(font=('times',12),width=50,height=15,wrap=WORD)
tx.pack(expand=YES,fill=BOTH)
tx.insert(1.0,'Дзен Пайтона\n\
Если интерпретатору дать команду\n\
import this ("импортировать это"),\n\
то выведется так называемый "Дзен Пайтона".\n Некоторые
выражения:\n\
* Если реализацию сложно объяснить — это плохая идея.\n\
* Ошибки никогда не должны замалчиваться.\n\
* Явное лучше неявного.\n\n')
47
Форматирование областей текста
#установка тегов для областей текста
tx.tag_add('title','1.0','1.end')
tx.tag_add('special','6.0','8.end')
tx.tag_add('special','3.0','3.11')
#конфигурирование тегов
tx.tag_config('title',foreground='red',
font=('times',14,'underline'),justify=CENTER)
tx.tag_config('special',background='grey85',font=('Dejavu',10,'bold'))
48
Добавление виджетов на текстовое поле
def erase():
tx.delete('1.0',END)
...
#добавление кнопки
bt = Button(tx,text='Стереть',command=erase)
tx.window_create(END,window=bt)
49
Добавление рисунка на текст
def smiley(event):
cv = Canvas(height=30,width=30)
cv.create_oval(1,1,29,29,fill="yellow")
cv.create_oval(9,10,12,12)
cv.create_oval(19,10,22,12)
cv.create_polygon(9,20,15,24,22,20)
tx.window_create(CURRENT,window=cv)
…
#ЛКМ -> смайлик
tx.bind('',smiley)
50
Работа с выделенным текстом
def style():
#установка тегов для областей текста
tx.tag_add('title',SEL_FIRST, SEL_LAST)
#конфигурирование тегов
tx.tag_config('title',foreground='red')
root=Tk()
tx = Text(root, font=('calibri',12),width=50,height=15,wrap=WORD)
tx.pack(expand=YES,fill=BOTH)
…
btn=Button(root,text='style',command=style)
btn.pack()
51
Работа с выделенным текстом
from tkinter import *
def style():
tagged=set()
tr=tx.tag_ranges('title')
for i in range(len(tr)//2):
startindex=len(tx.get(1.0,tr[2*i]))
endindex=len(tx.get(1.0,tr[2*i+1]))
tagged=tagged.union(set(range(startindex,endindex)))
seltext=tx.get(SEL_FIRST,SEL_LAST)
startindex=len(tx.get(1.0,SEL_FIRST))
endindex=startindex+len(seltext)
selected=set(range(startindex, endindex))
if tagged.intersection(selected)==selected:
tx.tag_remove('title',SEL_FIRST, SEL_LAST)
else:
tx.tag_add('title',SEL_FIRST, SEL_LAST)
root=Tk()
tx = Text(root, font=('calibri',12),width=50,height=15,wrap=WORD)
tx.pack(expand=YES,fill=BOTH)
#конфигурирование тегов
tx.tag_config('title',foreground='red')
btn=Button(root,text='style',command=style)
btn.pack()
52
Крестики-нолики с tkinter
x0='0'
from tkinter import *
class ButtonX(Button): #Производный класс от Button с дополнительным полем для хранения крестика или нолика
xx00=0
def newgame(event): #Подпрограмма очищает поле для новой игры
i=0
while i<3:
j=0
while j<3:
btns[i][j].xx00=0
btns[i][j].configure(text='')
j+=1
i+=1
lab.destroy()
new.destroy()
global x0 #Не забываем сделать так, чтобы крестики ходили первыми
x0='0'
def win(w): #При победе выводим результат и отображаем кнопку новой игры
global lab
global new
lab=Label(root)
if w=='x':
lab.configure(text='Победили крестики')
else:
lab.configure(text='Победили нолики')
lab.grid(columnspan=2)
new=Button(root,text='Снова')
new.grid(row=3,column=2)
new.bind('',newgame)
i=0
while i<3:
j=0
while j<3:
btns[i][j].xx00='wwww'
j+=1
i+=1
def step(event):
if not event.widget.xx00:
global x0
if x0=='0':
x0='x'
else:
x0='0'
event.widget.xx00=x0
i=event.widget.i
j=event.widget.j
event.widget.configure(text=x0)
n=0
for e in btns[i]:
if e.xx00==x0:
n+=1
if n==3:
win(x0)
n=0
for e in btns:
if e[j].xx00==x0:
n+=1
if n==3:
win(x0)
n=0
for e in range(0,3):
if btns[e][e].xx00==x0:
n+=1
if n==3:
win(x0)
n=0
for e in range(0,3):
if btns[e][2-e].xx00==x0:
n+=1
if n==3:
win(x0)
root=Tk()
root.title('gh')
root.configure(bg='white')
btns=[]
i=0
while i<3:
btns.append([])
j=0
while j<3:
btns[i].append(ButtonX(root,width=10,heig ht=5))
btns[i][j].i=i
btns[i][j].j=j
btns[i][j].grid(row=i,column=j)
btns[i][j].bind('',step)
j+=1
i+=1
root.mainloop()
53
Турнирная таблица
from tkinter import *
class Game:
def __init__(self,commands, winner='Unknown'):
self.commands=commands
while winner not in commands and winner!='Ничья':
print('Кто победил?')
winner=input()
if winner!='Ничья':
self.winner=winner
cm[self.winner].points+=3
else:
for e in commands:
cm[e].points+=1
class Command():
def __init__(self, points=0):
self.points=points
def table():
lab['text']=''
t=lambda x:cm[x].points
tbl=sorted(cm, key=t,reverse=True)
for e in tbl:
if e:
lab['text']+=str(e+' '+str(cm[e].points)+'\n')
def newgame():
def savegame():
commands=[ent1.get(),ent2.get()]
if var.get()==2:
wn='Ничья'
else:
wn=commands[var.get()]
game=Game(commands, wn)
f=open('table.txt','w')
for e in cm:
f.write(e+'\n')
f.write(str(cm[e].points)+'\n')
f.close()
table()
wnd=Toplevel()
lab1=Label(wnd, text='Команда 1')
ent1=Entry(wnd)
lab2=Label(wnd, text='Команда 2')
ent2=Entry(wnd)
var=IntVar()
var.set(2)
r1=Radiobutton(wnd, variable=var, value=0)
r2=Radiobutton(wnd, variable=var, value=1)
btnsave=Button(wnd,text='Сохранить ',command=sa vegame )
lab1.grid(row=0,column=0)
ent1.grid(row=0,column=1)
lab2.grid(row=1,column=0)
ent2.grid(row=1,column=1)
r1.grid(row=0,column=2)
r2.grid(row=1,column=2)
btnsave.grid(row=2,column=2)
cm={}
f=open('table.txt')
data=f.readlines()
for i in range(len(data)//2):
try:
cm[data[2*i][:-1]]=Command(points=int(dat a[2*i+1]))
except:
cm[data[2*i][:-1]]=Command()
f.close()
root=Tk()
lab=Label(root)
btn1=Button(root, text='Добавить игру', command=newgame)
lab.pack()
btn1.pack()
table()
root.mainloop()
54