Создание графических интерфейсов в питоне
План рассказа
- орг.: пора определяться с зачётным заданием
орг.: следующий раз будет 20-го числа
- передача параметров по имени
- откуда взялся Tk
- основные понятия Tk: виджет, настройки виджета, контейнер, упаковщик, события
- перерыв
- как делать программу с canvas
- как работать с временем / перерисовками
- преобразования пространства (масштабирование, смещение, поворот)
Контрольная работа
В переменных x и y лежат некоторые значения. Выполните такой набор действий, чтобы в x лежало то, что изначально было в y, а в y лежало то, что изначально было в x. Т.е. поменяйте эти две переменные значениями. Пример начала и конца диалога с питоном (заполните середину):
Напишите функцию fib(n), которая возвращает число ФИбоначчи с номером n. Числа Фибоначчи определяются следующим образом: f1 = f2 = 1, fn+2 = fn + fn+1. Первые числа Фибоначчи выглядят так: 1, 1, 2, 3, 5, 8, 13, ...
Пример графической программы
1 import Tkinter
2 import math
3
4 class Fun(object):
5 def __init__(self, canvas):
6 self.canvas = canvas
7 self.phi = 0
8 self.after_id = 0
9 def begin(self):
10 self.phi += 0.01
11 self.canvas.delete("all")
12 x, y = math.cos(self.phi) * 100 + 150, math.sin(self.phi) * 100 + 150
13 x0, y0 = x - 10, y - 10
14 x1, y1 = x + 10, y + 10
15 self.canvas.create_oval(x0, y0, x1, y1, fill="red")
16 self.after_id = canvas.after(10, self.begin)
17 def end(self):
18 self.canvas.after_cancel(self.after_id)
19
20 root = Tkinter.Tk()
21 root.title("Merry-go-round")
22
23 canvas = Tkinter.Canvas(root, background="black")
24 canvas.pack(fill="both", expand="yes")
25
26 fun = Fun(canvas)
27
28 panel = Tkinter.Frame(root)
29 panel.pack(fill="x")
30 go = Tkinter.Button(panel, text="Go", command=fun.begin)
31 go.pack(side="left", fill="both", expand="yes")
32 stop = Tkinter.Button(panel, text="Stop", command=fun.end)
33 stop.pack(side="left", fill="both", expand="yes")
34
35 root.mainloop()
Предупреждение: в теле примера для отступов используются табуляции, в то время, как в Idle по умолчанию используются пробелы. Смесь этих двух типов отступов чревата большим количеством головной боли. Idle умеет конвертировать отступы между табуляциями и пробелами. Выделите кусок текста и см. меню Format > Untabify. (Заодно поглядите, какие ещё полезные вещи есть в меню Format).
Документация
встроенные help()'ы
- Гугл?
Упражнения
Упражнения выполнять не обязательно, но если вы не представляете себе, как подступиться к задачам, то лучше сначала для тренировки повыполнять тупые упражнения, которые похожи на то, что творилось на доске.
- Разберитесь, как работает пример программы выше.
Напишите в файле excercise_hello.py программу, которая рисует графическое окошко с сообщением "hello, world", и ничего более не делает.
Напишите в файле excercise_figures.py программу, которая рисует окно с полотном (canvas), на котором нарисованы квадрат, круг и треугольник разных цветов.
Напишите в файле excercise_sine.py программу, которая рисует (крупно и понятно) график синусоиды.
Напишите в файле excercise_wave.py программу, которая рисует колеблющуюся волну: т.е. график синусоиды с постоянно изменяющейся фазой. (Суть задания в том, чтобы пользователь видел движущуюся картинку).
Задание
Задачи, помеченные (*) выполнять не обязательно. Пункт, помеченный (**) предназначен для крепких духом, желающих сделать красивую картинку своими руками.
- Приделайте к модели солнечной системы графический интерфейс. Первая графическая версия программы должна создавать окно, занятое целиком одним полотном (canvas), на котором в осмысленном масштабе рисуется солнечная система. Программа обновляет модель бесконечно, покуда пользователь не закроет окно.
- чтобы ситуация на экране стала интересной, нужно в любом случае хотя бы три сравнимо массивных тела; даже если вы не сделаете пункт 2, вам никто не мешает руками в файл вбить начальные данные какой-нибудь кометы, чтобы поглядеть на красивую картинку
- (*) Добавьте к интерфейсу способ добавлять планеты.
- добавьте массивную комету, пролетающую между Землёй и Солнцем, и поглядите, как она меняет поведение системы
- (*) Добавьте к интерфейсу способ менять начало координат, направление (**) и масштаб отображения (начало координат можно задавать инерциальным в какой-нибудь точке или связывать с какой-нибудь из планет; направление можно делать фиксированным в какую-нибудь сторону или связывать с азимутом с одной планеты на другую)
- добавьте планету, движущуюся по той же орбите, что и Земля, образующую с Солнцем правильный треугольник
- перейдите в систему отсчёта, связанную с Землёй и сориентированную по оси Земля-Солнце и поглядите на поведение системы
- добавьте планету, движущуюся по той же орбите, что и Земля, образующую с Солнцем правильный треугольник
Пошаговая инструкция к заданию 1 для негордых
Добавьте в класс Model поля canvas, scale, offset (и соответствующие аргументы конструктору)
Добавьте в класс Model метод draw, который сначала очищает canvas, затем рисует на нём кругами планеты
- лучше, чтобы планеты изображались разными цветами
- для кругов лучше задавать и параметр fill, и параметр outline
при рисовании используются параметры scale (на это число домножаются координаты и радиус планет) и offset (этот вектор прибавляется к координатам планет
Добавьте в класс Model метод run, который перерисовывает картинку на экране, делает шаг эмуляции и ставит таймер на перезапуск самого себя через 10мс.1
Добавьте в конец модуля astro код для создания окна Tk, создания на нём полотна, создания модели из имеющихся планет, полотна, и осмысленных значений для scale и offset (подумайте, какие значения были бы осмысленными), первичного запуска метода run в модели и запуска основного цикла Tk.
По-хорошему, тут бы должен был бы быть ещё один параметр timescale, который устанавливал бы зависимость между delta_t и интервалами, через которые мы перерисовываем картинку. Но как всегда. (1)