= Создание графических интерфейсов в питоне = [[/Record|Конспект]] == План рассказа == * орг.: пора определяться с зачётным заданием * орг.: следующий раз будет 20-го числа :( * передача параметров по имени * откуда взялся Tk * основные понятия Tk: виджет, настройки виджета, контейнер, упаковщик, события * перерыв * как делать программу с canvas * как работать с временем / перерисовками * преобразования пространства (масштабирование, смещение, поворот) == Контрольная работа == 1. В переменных {{{x}}} и {{{y}}} лежат некоторые значения. Выполните такой набор действий, чтобы в {{{x}}} лежало то, что изначально было в {{{y}}}, а в {{{y}}} лежало то, что изначально было в {{{x}}}. Т.е. поменяйте эти две переменные значениями. Пример начала и конца диалога с питоном (заполните середину): {{{#!python >>> x = 99 >>> y = "hello" >>> x 'hello' >>> y 99 }}} 2. Напишите функцию {{{fib(n)}}}, которая возвращает число ФИбоначчи с номером {{{n}}}. Числа Фибоначчи определяются следующим образом: ''f,,1,, = f,,2,, = 1, f,,n+2,, = f,,n,, + f,,n+1,,''. Первые числа Фибоначчи выглядят так: 1, 1, 2, 3, 5, 8, 13, ... == Пример графической программы == {{{#!python import Tkinter import math class Fun(object): def __init__(self, canvas): self.canvas = canvas self.phi = 0 self.after_id = 0 def begin(self): self.phi += 0.01 self.canvas.delete("all") x, y = math.cos(self.phi) * 100 + 150, math.sin(self.phi) * 100 + 150 x0, y0 = x - 10, y - 10 x1, y1 = x + 10, y + 10 self.canvas.create_oval(x0, y0, x1, y1, fill="red") self.after_id = canvas.after(10, self.begin) def end(self): self.canvas.after_cancel(self.after_id) root = Tkinter.Tk() root.title("Merry-go-round") canvas = Tkinter.Canvas(root, background="black") canvas.pack(fill="both", expand="yes") fun = Fun(canvas) panel = Tkinter.Frame(root) panel.pack(fill="x") go = Tkinter.Button(panel, text="Go", command=fun.begin) go.pack(side="left", fill="both", expand="yes") stop = Tkinter.Button(panel, text="Stop", command=fun.end) stop.pack(side="left", fill="both", expand="yes") root.mainloop() }}} {{{#!wiki note Предупреждение: в теле примера для отступов используются табуляции, в то время, как в Idle по умолчанию используются пробелы. Смесь этих двух типов отступов чревата большим количеством головной боли. Idle умеет конвертировать отступы между табуляциями и пробелами. Выделите кусок текста и см. меню Format > Untabify. (Заодно поглядите, какие ещё полезные вещи есть в меню Format). }}} == Документация == * [[http://www.tutorialspoint.com/python/python_gui_programming.htm|Неофициальный туториал]] * встроенные {{{help()}}}'ы * [[http://docs.python.org/library/tkinter.html|Официальная справочная документация]] * [[http://www.pythonware.com/library/tkinter/introduction/index.htm|Почти официальный туториал по Tkinter]] * [[Href:~dendik/data/python/2010-04-06/Tkinter.ppt|Презентация Леси Денисенко с прошлого года]] * Гугл? == Упражнения == Упражнения выполнять не обязательно, но если вы не представляете себе, как подступиться к задачам, то лучше сначала для тренировки повыполнять тупые упражнения, которые похожи на то, что творилось на доске. 1. Разберитесь, как работает пример программы выше. 1. Напишите в файле {{{excercise_hello.py}}} программу, которая рисует графическое окошко с сообщением "hello, world", и ничего более не делает. 2. Напишите в файле {{{excercise_figures.py}}} программу, которая рисует окно с полотном (canvas), на котором нарисованы квадрат, круг и треугольник разных цветов. 3. Напишите в файле {{{excercise_sine.py}}} программу, которая рисует (крупно и понятно) график синусоиды. 4. Напишите в файле {{{excercise_wave.py}}} программу, которая рисует колеблющуюся волну: т.е. график синусоиды с постоянно изменяющейся фазой. (Суть задания в том, чтобы пользователь видел движущуюся картинку). == Задание == Задачи, помеченные (*) выполнять не обязательно. Пункт, помеченный (**) предназначен для крепких духом, желающих сделать красивую картинку своими руками. 1. Приделайте к модели солнечной системы графический интерфейс. Первая графическая версия программы должна создавать окно, занятое целиком одним полотном (canvas), на котором в осмысленном масштабе рисуется солнечная система. Программа обновляет модель бесконечно, покуда пользователь не закроет окно. * чтобы ситуация на экране стала интересной, нужно в любом случае хотя бы три сравнимо массивных тела; даже если вы не сделаете пункт 2, вам никто не мешает руками в файл вбить начальные данные какой-нибудь кометы, чтобы поглядеть на красивую картинку 2. (*) Добавьте к интерфейсу способ добавлять планеты. * добавьте массивную комету, пролетающую между Землёй и Солнцем, и поглядите, как она меняет поведение системы 3. (*) Добавьте к интерфейсу способ менять начало координат, направление (**) и масштаб отображения (начало координат можно задавать инерциальным в какой-нибудь точке или связывать с какой-нибудь из планет; направление можно делать фиксированным в какую-нибудь сторону или связывать с азимутом с одной планеты на другую) * добавьте планету, движущуюся по той же орбите, что и Земля, образующую с Солнцем правильный треугольник * перейдите в систему отсчёта, связанную с Землёй и сориентированную по оси Земля-Солнце и поглядите на поведение системы == Пошаговая инструкция к заданию 1 для негордых == 1. Добавьте в класс {{{Model}}} поля {{{canvas}}}, {{{scale}}}, {{{offset}}} (и соответствующие аргументы конструктору) 2. Добавьте в класс {{{Model}}} метод {{{draw}}}, который сначала очищает {{{canvas}}}, затем рисует на нём кругами планеты * лучше, чтобы планеты изображались разными цветами * для кругов лучше задавать и параметр fill, и параметр outline * при рисовании используются параметры {{{scale}}} (на это число домножаются координаты и радиус планет) и {{{offset}}} (этот вектор прибавляется к координатам планет 3. Добавьте в класс {{{Model}}} метод {{{run}}}, который перерисовывает картинку на экране, делает шаг эмуляции и ставит таймер на перезапуск самого себя через 10мс.<<FootNote(По-хорошему, тут бы должен был бы быть ещё один параметр timescale, который устанавливал бы зависимость между delta_t и интервалами, через которые мы перерисовываем картинку. Но как всегда.)>> 4. Добавьте в конец модуля astro код для создания окна Tk, создания на нём полотна, создания модели из имеющихся планет, полотна, и осмысленных значений для {{{scale}}} и {{{offset}}} (подумайте, какие значения были бы осмысленными), первичного запуска метода run в модели и запуска основного цикла Tk. ## vim: set ts=4 sts=4 et: