Управление яркостью светодиода. АЦП – ЦАП
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Примером реализации схемы подключения потенциометра может стать макетная плата с подключенным переменным резистором и светодиодом. При помощи потенциометра будет выполняться управление уровнем яркости свечения.
Для проведения работ следует подготовить такие детали:

· 1 плату Arduino Uno

· 1 беспаячную макетную плату

· 1 светодиод

· 1 резистор с сопротивлением 220 Ом

· 6 проводов «папа-папа»

· 1 потенциометр..


Для использования меньшего количества проводов от макетной платы к контроллеру следует подключить светодиод и потенциометр проводом земли к длинному рельсу минуса.
Пример скетча. В этом примере важно понимать, что яркость свечения светодиода управляется не напряжением, подаваемым с потенциометра, а кодом.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #define PIN_LED 11 #define PIN_POT A0   void setup() { // Пин, к которому подсоединяется светодиод определяем как выход pinMode(PIN_LED, OUTPUT);   // Пин с переменным резистором является входом pinMode(PIN_POT, INPUT); }   void loop(){ // Определяем 2 переменные типа int int rotat, brightn;   // Считывание в переменную rotat напряжения с переменного резистора: // микроконтроллер будет выдавать числа от 0 до 1023 // пропорциональны положению поворота вала rotat = analogRead(PIN_POT);   // Преобразуем значение в яркость. Для этого делим rotat на 4, что с учетом округления даст нам число от 0 до 255. Именно это число мы подадим на шим-выход, с помощью которого можно управлять яркостью.   brightn = rotat / 4;   // Запись шим значения яркости на светодиод analogWrite(PIN_LED, brightn); }

 

 

****************************************************************

Лаб_5 - Программирование Питон IDLE GUI

Примеры создания типовых элементов GUI Tkinter



Класс Tk

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

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

  





Button

Виджет Button - самая обыкновенная кнопка, которая используется в тысячах программ. Пример кода:

 

from Tkinter import *

root=Tk()

button1=Button(root,text='ok',14')

Button1.pack()

Root.mainloop()

 

Разберем этот небольшой код. За создание, собственно, окна, отвечает класс Tk(), и первым делом нужно создать экземпляр

этого класса. Этот экземпляр принято называть root, хотя вы можете назвать его как угодно. Далее создаётся кнопка, при

этом мы указываем её свойства (начинать нужно с указания окна, в примере - root). Здесь перечислены некоторые из них:

text - какой текст будет отображён на кнопке (в примере - ок)

width,height - соответственно, ширина и длина кнопки.

bg - цвет кнопки (сокращенно от background, в примере цвет - чёрный)

fg - цвет текста на кнопке (сокращённо от foreground, в примере цвет - красный)

font - шрифт и его размер (в примере - arial, размер - 14)

Далее, нашу кнопку необходимо разместить на окне. Для этого, в Tkinter используются специальные упаковщики( pack(),

place(), grid() ). Поподробнее об упаковщиках узнаем позже. Пока, чтобы разместить несколько виджетов на окне, будем

применять самый простой упаковщик pack(). В конце программы, нужно использовать функцию mainloop (см. пример),

иначе окно не будет создано.

 

Label

Label - это виджет, предназначенный для отображения какой-либо надписи без возможности редактирования пользователем.

Имеет те же свойства, что и перечисленные свойства кнопки.

 

Entry

Entry - это виджет, позволяющий пользователю ввести одну строку текста. Имеет дополнительное свойство bd (сокращённо от borderwidth), позволяющее регулировать ширину границы.

borderwidth - ширина бордюра элемента

bd - сокращение от borderwidth

width - задаёт длину элемента в знакоместах.

show - задает отображаемый символ.

 

Text

Text - это виджет, который позволяет пользователю ввести любое количество текста. Имеет дополнительное свойство wrap,

отвечающее за перенос (чтобы, например, переносить по словам, нужно использовать значение WORD). Например:

 

from Tkinter import *

root=Tk()

text1=Text(root,height=7,14',wrap=WORD)

Text1.pack()

Root.mainloop()

 

Методы insert, delete и get добавляют, удаляют или извлекают текcт. Первый аргумент - место вставки в виде 'x.y', где x – это

строка, а y – столбец. Например:

 

text 1. insert (1.0,'Добавить Текст \ n \ в начало первой строки' )

Text1.delete('1.0', END) # Удалить все

Text1.get('1.0', END) # Извлечь все

 

Listbox

Listbox - это виджет, который представляет собой список, из элементов которого пользователь может выбирать один или

несколько пунктов. Имеет дополнительное свойство selectmode, которое, при значении SINGLE, позволяет пользователю

выбрать только один элемент списка, а при значении EXTENDED - любое количество. Пример:

 

from Tkinter import *

root=Tk()

listbox1=Listbox(root,height=5,

listbox2=Listbox(root,height=5,

list1=[u"Москва",u"Санкт-Петербург" ,u"Саратов",u"Омск"]

list2=[u"Канберра",u"Сидней",u"Мельбурн",u"Аделаида"]

For i in list1:

listbox1.insert(END,i)

For i in list2:

listbox2.insert(END,i)

Listbox1.pack()

Listbox2.pack()

Root.mainloop()

 

Стоит заметить, что в этой библиотеке для того, чтобы использовать русские буквы в строках, нужно использовать Unicode-

строки. В Python 2.x для этого нужно перед строкой поставить букву u, в Python 3.x этого делать вообще не требуется, т.к.

все строки в нем изначально Unicode. Кроме того в первой или второй строке файла необходимо указать кодировку файла (в комментарии): coding: utf-8. Чаще всего используется формат в стиле текстового редактора emacs:

# encoding : utf -8

В Python 3.x кодировку файла можно не указывать, в этом случае по умолчанию предполагается utf-8.

 

Frame

Виджет Frame (рамка) предназначен для организации виджетов внутри окна. Рассмотрим пример:

 

from tkinter import *

root=Tk()

frame1=Frame(root,bg='green',bd=5)

frame2=Frame(root,bg='red',bd=5)

button1=Button(frame1,text=u'Первая кнопка' )

button2=Button(frame2,text=u'Вторая кнопка' )

Frame1.pack()

Frame2.pack()

Button1.pack()

Button2.pack()

Root.mainloop()

Свойство bd отвечает за толщину края рамки.

 

Checkbutton

Checkbutton - это виджет, который позволяет отметить „галочкой“ определенный пункт в окне. При использовании

нескольких пунктов нужно каждому присвоить свою переменную. Разберем пример:

 

from tkinter import *

root=Tk()

var1=IntVar()

var2=IntVar()

check1=Checkbutton(root,text=u'1 пункт',variable=var1,onvalue=1,offvalue=0)

check2=Checkbutton(root,text=u'2 пункт',variable=var2,onvalue=1,offvalue=0)

Check1.pack()

Check2.pack()

Root.mainloop()

 

IntVar() - специальный класс библиотеки для работы с целыми числами. variable - свойство, отвечающее за прикрепление к

виджету переменной. onvalue, offvalue - свойства, которые присваивают прикреплённой к виджету переменной значение,

которое зависит от состояния(onvalue - при выбранном пункте, offvalue - при невыбранном пункте).

 

Radiobutton

Виджет Radiobutton выполняет функцию, схожую с функцией виджета Checkbutton. Разница в том, что в виджете Radiobutton

пользователь может выбрать лишь один из пунктов. Реализация этого виджета несколько иная, чем виджета Checkbutton:

 

from tkinter import *

root=Tk()

var=IntVar()

rbutton1=Radiobutton(root,text='1',variable=var,value=1)

rbutton2=Radiobutton(root,text='2',variable=var,value=2)

rbutton3=Radiobutton(root,text='3',variable=var,value=3)

Rbutton1.pack()

Rbutton2.pack()

Rbutton3.pack()

Root.mainloop()

 

В этом виджете используется уже одна переменная. В зависимости от того, какой пункт выбран, она меняет своё значение.

Самое интересное, что если присвоить этой переменной какое-либо значение, поменяется и выбранный виджет. На этом мы

прервём изучение типов виджетов (потом мы к ним обязательно вернёмся).

 

Scale

Scale (шкала) - это виджет, позволяющий выбрать какое-либо значение из заданного диапазона. Свойства:

orient - как расположена шкала на окне. Возможные значения: HORIZONTAL, VERTICAL (горизонтально,

вертикально).

length - длина шкалы.

from_ - с какого значения начинается шкала.

to - каким значением заканчивается шкала.

tickinterval - интервал, через который отображаются метки шкалы.

resolution - шаг передвижения (минимальная длина, на которую можно передвинуть движок)

Пример кода:

 

from tkinter import *

root = Tk()

Def getV(root):

a = scale1.get()

print "Значение", a

scale1 = Scale(root,orient=HORIZONTAL,length=300,from_=50,to=80,tickinterval=5,

 resolution=5)

button1 = Button(root,text=u"Получить значение" )

Scale1.pack()

Button1.pack()

button1.bind("<Button-1>",getV)

Root.mainloop()

 

Здесь используется специальный метод get(), который позволяет снять с виджета определенное значение, и используется не только в Scale.

 

Scrollbar

Scrollbar – этот виджет даёт возможность пользователю "прокрутить" другой виджет (например текстовое поле) и часто бывает

полезен. Использование этого виджета достаточно нетривиально. Необходимо сделать две привязки: command полосы

прокрутки привязываем к методу xview/yview виджета, а xscrollcommand/yscrollcommand виджета привязываем к методу set

полосы прокрутки.

Рассмотрим на примере:

from tkinter import *

root = Tk()

text = Text(root, height=3,

text.pack(side='left')

scrollbar = Scrollbar(root)

scrollbar.pack(side='left')

# первая привязка

scrollbar['command'] = text.yview

# вторая привязка

text['yscrollcommand' ] = scrollbar.set

Root.mainloop()

 

Упаковщики

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

Разберем каждый из них по порядку:

Pack()

Упаковщик pack() является самым интеллектуальным (и самым непредсказуемым). При использовании этого упаковщика с

помощью свойства side нужно указать к какой стороне родительского виджета он должен примыкать. Как правило этот

упаковщик используют для размещения виджетов друг за другом (слева направо или сверху вниз). Пример:

from tkinter import *

root=Tk()

button1 = Button(text="1")

button2 = Button(text="2")

button3 = Button(text="3")

button4 = Button(text="4")

button5 = Button(text="5")

button1.pack(side='left')

button2.pack(side='top')

button3.pack(side='left')

button4.pack(side='bottom')

button5.pack(side='right')

Root.mainloop()

 

Результат работы можно увидеть на скриншоте справа.

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

вложенные друг в друга.

Аргументы:

При применении этого упаковщика можно указать следующие аргументы:

side ("left"/"right"/"top"/"bottom") - к какой стороне должен примыкать размещаемый виджет.

fill (None/"x"/"y"/"both") - необходимо ли расширять пространство предоставляемое виджету.

expand (True/False) - необходимо ли расширять сам виджет, чтобы он занял всё предоставляемое ему

пространство.

in_ - явное указание в какой родительский виджет должен быть помещён.

Дополнительные функции

Кроме основной функции у виджетов есть дополнительные методы для работы с упаковщиками.

pack_configure - синоним для pack.

pack_slaves (синоним slaves) - возвращает список всех дочерних упакованных виджетов.

pack_info - возвращает информацию о конфигурации упаковки.

pack_propagate (синоним propagate) (True/False) - включает/отключает распространении информации о

геометрии дочерних виджетов. По умолчанию виджет изменяет свой размер в соответствии с размером своих

потомков. Этот метод может отключить такое поведение (pack_propagate(False)). Это может быть полезно,

если необходимо, чтобы виджет имел фиксированный размер и не изменял его по прихоти потомков.[7]

pack_forget (синоним forget) - удаляет виджет и всю информацию о его расположении из упаковщика.

Позднее этот виджет может быть снова размещён.

 

Grid()

Этот упаковщик представляет собой таблицу с ячейками, в которые помещаются виджеты.

Аргументы:

row - номер строки, в который помещаем виджет.

rowspan - сколько строк занимает виджет

column - номер столбца, в который помещаем виджет.

columnspan - сколько столбцов занимает виджет.

padx / pady - размер внешней границы (бордюра) по горизонтали и вертикали.

ipadx / ipady - размер внутренней границы (бордюра) по горизонтали и вертикали. Разница между pad и ipad

в том, что при указании pad расширяется свободное пространство, а при ipad расширяется помещаемый

виджет.

sticky ("n", "s", "e", "w" или их комбинация) - указывает к какой границе "приклеивать" виджет. Позволяет

расширять виджет в указанном направлении. Границы названы в соответствии со сторонами света. "n"

(север) - верхняя граница, "s" (юг) - нижняя, "w" (запад) - левая, "e" (восток) - правая.

in_ - явное указание в какой родительский виджет должен быть помещён.

 

Для каждого виджета указываем, в какой он находится строке, и в каком столбце. Если нужно, указываем, сколько ячеек он

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

Пример:

 

entry1.grid(row=0,column=0,columnspan=3)

button1.grid(row=1,column=0)

button2.grid(row=1,column=1)

button3.grid(row=1,column=2)

 

Дополнительные функции

grid_configure - синоним для grid.

grid_slaves (синоним slaves) - см. pack_slaves.

grid_info - см. pack_info.

grid_propagate (синоним propagate) - см. pack_propagate.

grid_forget (синоним forget) - см. pack_forget.

grid_remove - удаляет виджет из-под управления упаковщиком, но сохраняет информацию об упаковке. Этот

метод удобно использовать для временного удаления виджета (см. пример в описании метода destroy).

grid_bbox (синоним bbox) - возвращает координаты (в пикселях) указанных столбцов и строк.[9]

grid_location (синоним location) - принимает два аргумента: x и y (в пикселях). Возвращает номер строки и

столбца в которые попадают указанные координаты, либо -1 если координаты попали вне виджета.

grid_size (синоним size) - возвращает размер таблицы в строках и столбцах.

grid_columnconfigure (синоним columnconfigure) и grid_rowconfigure (синоним rowconfigure) - важные

функции для конфигурирования упаковщика. Методы принимают номер строки/столбца и аргументы

конфигурации. Список возможных аргументов:

minsize - минимальная ширина/высота строки/столбца.

weight - "вес" строки/столбца при увеличении размера виджета. 0 означает, что строка/столбец не будет

расширяться. Строка/столбец с "весом" равным 2 будет расширяться вдвое быстрее, чем с весом 1.

uniform - объединение строк/столбцов в группы. Строки/столбцы имеющие одинаковый параметр uniform

будут расширяться строго в соответствии со своим весом.

pad - размер бордюра. Указывает, сколько пространства будет добавлено к самому большому виджету в

строке/столбце.

 

Пример, текстовый виджет с двумя полосами прокрутки:

 

from tkinter import *

root=Tk()

text = Text(wrap=NONE)

vscrollbar = Scrollbar(orient='vert', command=text.yview)

text['yscrollcommand' ] = vscrollbar.set

hscrollbar = Scrollbar(orient='hor', command=text.xview)

text['xscrollcommand' ] = hscrollbar.set

# размещаем виджеты

text.grid(row=0, column=0, sticky='nsew')

vscrollbar.grid(row=0, column=1, sticky='ns')

hscrollbar.grid(row=1, column=0, sticky='ew')

# конфигурируем упаковщик, чтобы текстовый виджет расширялся

root.rowconfigure(0, weight=1)

root.columnconfigure (0, weight=1)

Root.mainloop()

 

Place()

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

размером. Также он позволяет указывать координаты размещения в относительных единицах для реализации "резинового"

размещения. При использовании этого упаковщика, нам необходимо указывать координаты каждого виджета. Например:

 

button1.place(x=0,y=0)

 

Этот упаковщик, хоть и кажется неудобным, предоставляет полную свободу в размещении виджетов на окне.

Аргументы:

anchor ("n", "s", "e", "w", "ne", "nw", "se", "sw" или "center") - какой угол или сторона размещаемого виджета будет указана в аргументах x/y/relx/rely. По умолчанию "nw" - левый верхний

bordermode ("inside", "outside", "ignore") - определяет в какой степени будут учитываться границы при размещении виджета.

in_ - явное указание в какой родительский виджет должен быть помещён.

x и y - абсолютные координаты (в пикселях) размещения виджета.

width и height - абсолютные ширина и высота виджета.

relx и rely - относительные координаты (от 0.0 до 1.0) размещения виджета.

relwidth и relheight - относительные ширина и высота виджета.

 

Относительные и абсолютные координаты (а также ширину и высоту) можно комбинировать. Так например, relx=0.5,

x=-2 означает размещение виджета в двух пикселях слева от центра родительского виджета, relheight=1.0,

height=-2 - высота виджета на два пикселя меньше высоты родительского виджета.

Дополнительные функции:

place_slaves, place_forget, place_info - см. описание аналогичных методов упаковщика pack.

 

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

Command

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


bind()

Метод bind[1] привязывает событие к какому-либо действию (нажатие кнопки мыши, нажатие клавиши на клавиатуре и т.д.).
bind принимает три аргумента:
название события
функцию, которая будет вызвана при наступлении события
третий аргумент (необязательный) - строка "+" - означает, что эта привязка добавляется к уже существующим.
Если третий аргумент опущен или равен пустой строке - привязка замещает все другие привязки данного
события к виджету.
Метод bind возвращает идентификатор привязки, который может быть использован в функции unbind.
Обратите внимание, что если bind привязан к окну верхнего уровня, то Tkinter будет обрабатывать события всех виджетов
этого окна (см. также bind_all ниже).
Функция, которая вызывается при наступлении события, должна принимать один аргумент. Это объект класса Event, в котором описано наступившее событие. Объект класса Event имеет следующие атрибуты (в скобках указаны события, для которых этот атрибут установлен):
serial - серийный номер события (все события)
num - номер кнопки мыши (ButtonPress, ButtonRelease)
focus - имеет ли окно фокус (Enter, Leave)
height и width - ширина и высота окна (Configure, Expose)
keycode - код нажатой клавиши (KeyPress, KeyRelease)
state - состояние события (для ButtonPress, ButonRelease, Enter, KeyPress, КeyRelease, Leave, Motion - в
виде числа; для Visibility - в виде строки)
time - время наступления события (все события)
x и y - координаты мыши
x _ root и y _ root - координаты мыши на экране (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion)
char - набранный на клавиатуре символ (KeyPress, KeyRelease)
send _ event - см. документацию по X/Windows
keysym - набранный на клавиатуре символ (KeyPress, KeyRelease)
keysym _ num- набранный на клавиатуре символ в виде числа (KeyPress, KeyRelease)
type - тип события в виде числа (все события)
widget - виджет, который получил событие (все события)
delta - изменение при вращении колеса мыши (MouseWheel)
Эта функция может возвращать строки "continue" и "break". Если функция возвращает "continue" то Tkinter продолжит обработку других привязок этого события, если "break" - обработка этого события прекращается. Если функция ничего не возвращает (если возвращает None), то обработка событий продолжается (т.е. это эквивалентно возвращению "continue").

Названия событий
Есть три формы названия событий. Самый простой случай это символ ASCII. Так описываются события нажатия клавиш на
клавиатуре:
widget . bind( "z" , callback )


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


Список модификаторов
Return
- Enter
Escape - Esc
Control - Ctrl
Alt
Shift
Lock
Extended

Prior - PgUp
Next - PgDown
Button1, B1 - нажата первая (левая) кнопка мыши
Button2, B2 - вторая (средняя) кнопка мыши
Button3, B3 - третья (правая)
Button4, B4 - четвёртая
Button5, B5 - пятая
Mod1, M1, Command
Mod2, M2, Option
Mod3, M3
Mod4, M4
Mod5, M5
Meta, M
Double
- двойной щелчок мыши (например, <Double-Button-1>)
Triple - тройной
Quadruple - четверной

Типы событий
Здесь перечислены все возможные типы событий, для самых часто используемых дано описание. Более подробно см. man bind.
Activate, Deactivate
MouseWheel
- прокрутка колесом мыши
KeyPress, KeyRelease- нажатие и отпускание клавиши на клавиатуре
ButtonPress, ButtonRelease, Motion- нажатие, отпускание клавиши мыши, движение мышью
Configure - изменение положения или размера окна
Map, Unmap- показывание или сокрытие окна (например, в случае сворачивания/разворачивания окна пользователем)
Visibility
Expose
- событие генерируется, когда необходимо всё окно или его часть перерисовать
Destroy - закрытие окна
FocusIn, FocusOut- получение или лишение фокуса
Enter, Leave - Enter генерируется когда курсор мыши "входит" в окно, Leave - когда "уходит" из окна
Property
Colormap
MapRequest, CirculateRequest, ResizeRequest, ConfigureRequest, Create
Gravity, Reparent, Circulate

Клавиатурные символы
Полный список см.man keysyms.
Примеры
<Button-1>или <1> - нажата левая клавиша мыши.
<Alt-Motion>- движение мышью с нажатой на клавиатуре клавишей Alt.
<Key> - нажатие любой клавиши на клавиатуре.
Пример:

from Tkinter import *
root = Tk()
def leftclick (event):
print u'Вы нажали левую кнопку мыши'
def rightclick (event):
print u'Вы нажали правую кнопку мыши'
button1=Button(root, text=u'Нажми')
button1.pack()
button1.bind('<Button-1>' , leftclick )
button1.bind('<Button-3>' , rightclick )
root.mainloop ()

Дополнительные методы
bind_all
- создаёт привязку для всех виджетов приложения. Отличие от привязки к окну верхнего уровня
заключается в том, что в случае привязки к окну привязываются все виджеты этого окна, а этот метод
привязывает все виджеты приложения (у приложения может быть несколько окон).
bind_class - создаёт привязку для всех виджетов данного класса

 

Пример:
from Tkinter import *
def callback (e):
print u'Нажата кнопка' , e . widget[ 'text' ]
root = Tk()
button1 = Button(root, text = '1' )
button1 . pack()
button2 = Button(root, text = '2' )
button2 . pack()
root . bind_class ( 'Button' , '<1>' , callback )
root . mainloop ()

bindtags - позволяет изменить порядок обработки привязок. По умолчанию порядок следующий: виджет,
класс, окно, all; где виджет - привязка к виджету (bind), класс - привязка к классу (bind_class), окно - привязка к
окну (root.bind), all - привязка всех виджетов (bind_all).

 

Пример, меняем порядок обработки привязок на обратный:

from Tkinter import *
def callback1 (e): print 'callback1'
def callback2 (e): print 'callback2'
def callback3 (e): print 'callback3'
def callback4 (e): print 'callback4'
root = Tk()
button = Button(root)
button . pack()
button . bind( '<1>' , callback1 )
root . bind_class ( 'Button' , '<1>' , callback2 )
root . bind( '<1>' , callback3 )
root . bind_all ( '<1>' , callback4 )
button . bindtags (( 'all' , root, 'Button' , button))
root . mainloop ()

unbind - отвязать виджет от события. В качестве аргумента принимает идентификатор, полученный от
метода bind.
unbind_all - то же, что и unbind, только для метода bind_all.
unbind_class- то же, что и unbind, только для метода bind_class

 

****************************************************************

Лаб_6 - Программирование Питон PyGame . Классы

Познакомимся с основами ООП - использованием с классов в Python, на примере собственной игры «Wild West». Игра создана на основе кода игры «Alien» подробно описанной в этой книге - Эрик Мэтиз. Изучаем Питон. Программирование игр, визуализация данных, веб-приложения. Питер. 2017.  

Для создание игровых аудио и видео эффектов, которых нет в исходном примере, используем собственные аудио и видео образы:

         

 

Код программы

----------------------------------------------------------------------------------------------------------

alien_invasion.py

 

import pygame

from pygame.sprite import Group

from pygame.sprite import GroupSingle

import myvar

 

from settings import Settings

from game_stats import GameStats

from scoreboard import Scoreboard

from button import Button

from ship import Ship

import game_functions as gf

 

pygame.mixer.music.load('audio/music.wav')

pygame.mixer.music.set_volume(0.3)

pygame.mixer.music.play(-1)

 

def run_game():

# Initialize pygame, settings, and screen object.

pygame.init()

ai_settings = Settings()

screen = pygame.display.set_mode(

   (ai_settings.screen_width, ai_settings.screen_height))

clock = pygame.time.Clock()

   

# впишем фон игры и название огры

screen.blit(myvar.my_image, (0, 0))    ##   

pygame.display.set_caption("Western 1.0")

   

# Make the Play button.

play_button = Button(ai_settings, screen, "Play")

   

# Create an instance to store game statistics, and a scoreboard.

stats = GameStats(ai_settings)

sb = Scoreboard(ai_settings, screen, stats)

    

   

# Make a ship, a group of bullets, and a group of aliens.

ship = Ship(ai_settings, screen)

bullets = Group()

aliens = Group()

gbullets = Group()

# создадим группу основного игрового ship   

m_ships = GroupSingle()

m_ships.add(ship)

   

   

# Create the fleet of aliens.

gf.create_fleet(ai_settings, screen, aliens)

 

# Start the main loop for the game.

while True:

   gf.check_events(ai_settings, screen, stats, sb, play_button, m_ships,

       aliens, bullets)

       

   if stats.game_active:           

       gf.update_ships(m_ships)        

       bullets.clear(screen, myvar.my_image)

       gf.update_bullets(ai_settings, screen, stats, sb, m_ships, aliens,

                        bullets)

       gbullets.clear(screen, myvar.my_image)

       gf.update_gbullets(ai_settings, screen, stats, sb, m_ships, aliens,

                          gbullets)

       gf.update_aliens(ai_settings, screen, stats, sb, m_ships, aliens,

           bullets, gbullets)

       

   gf.update_screen(ai_settings, screen, stats, sb, m_ships, aliens,

       bullets, gbullets, play_button)

 

   clock.tick(200)

 

run_game()

 

----------------------------------------------------------------------------------------------------------

game_functions.py

 

import sys

from time import sleep

import pygame

import myvar

 

 

from bullet import Bullet

from gbullet import Gbullet

from alien import Alien

from ship import Ship

 

pygame.init() ##

bgr_img = myvar.my_image

shoot_sound1 = pygame.mixer.Sound('audio/shooter.wav') ## звук выстрела ship

shoot_sound2 = pygame.mixer.Sound('audio/sh_reload.wav') ## звук перезарядки ship

shoot_sound3 = pygame.mixer.Sound('audio/alien.wav') ## звук крика alien

shoot_sound4 = pygame.mixer.Sound('audio/ship.wav') ## звук крика ship

shoot_sound5 = pygame.mixer.Sound('audio/guns.wav') ## звук выстрела alien

 

def check_keydown_events(event, ai_settings, screen, m_ships, bullets):

"""Respond to keypresses."""

if event.key == pygame.K_RIGHT:

   for ship in m_ships:

       ship.moving_right = True

elif event.key == pygame.K_LEFT:

   for ship in m_ships:

       ship.moving_left = True

elif event.key == pygame.K_SPACE:

   fire_bullet(ai_settings, screen, m_ships, bullets)

elif event.key == pygame.K_q:

   pygame.quit()

   sys.exit()       

       

def check_keyup_events(event, m_ships):

"""Respond to key releases."""

if event.key == pygame.K_RIGHT:

   for ship in m_ships:

       ship.moving_right = False

elif event.key == pygame.K_LEFT:

   for ship in m_ships:

       ship.moving_left = False

 

def check_events(ai_settings, screen, stats, sb, play_button, m_ships, aliens,

   bullets):

"""Respond to keypresses and mouse events."""

for event in pygame.event.get():

   if event.type == pygame.QUIT:

       sys.exit()

   elif event.type == pygame.KEYDOWN:

       check_keydown_events(event, ai_settings, screen, m_ships, bullets)

   elif event.type == pygame.KEYUP:

       check_keyup_events(event, m_ships)

   elif event.type == pygame.MOUSEBUTTONDOWN:

       mouse_x, mouse_y = pygame.mouse.get_pos()

       check_play_button(ai_settings, screen, stats, sb, play_button,

           m_ships, aliens, bullets, mouse_x, mouse_y)

           

def check_play_button(ai_settings, screen, stats, sb, play_button, m_ships,

   aliens, bullets, mouse_x, mouse_y):

"""Start a new game when the player clicks Play."""

button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)

if button_clicked and not stats.game_active:

   # Reset the game settings.

   ai_settings.initialize_dynamic_settings()

       

   # Hide the mouse cursor.

   pygame.mouse.set_visible(False)

       

   # Reset the game statistics.

   stats.reset_stats()

   stats.game_active = True

   # Установим флаг активации кнопки для погашения

   stats.game_button_pressed = True 

       

   # Reset the scoreboard images.

   sb.prep_score()

   sb.prep_high_score()

   sb.prep_level()

   sb.prep_ships()

       

   # Empty the list of aliens and bullets.

   aliens.empty()

   bullets.empty()

   m_ships.empty()

       

   # Create a new fleet and center the ship.

   create_fleet(ai_settings, screen, aliens)

   # создаем новый объект ship

   ship = Ship(ai_settings, screen)

   ship.center_ship()

   m_ships.add(ship)       

 

def fire_bullet(ai_settings, screen, m_ships, bullets):

"""Fire a bullet, if limit not reached yet."""

# Create a new bullet, add to bullets group.

if len(bullets) < ai_settings.bullets_allowed:

   for ship in m_ships:

       new_bullet = Bullet(ai_settings, screen, ship)

       ship.aliene_fight = True # Установить флаг ответного огня противника

   bullets.add(new_bullet)       

   shoot_sound1.play() ## выстрел

   sleep(0.3)      ##

   shoot_sound2.play() ## перезарядка

   sleep(0.3)

 

   

def fire_gbullet(ai_settings, screen, m_ships, bullets, aliens, gbullets):

""" ответный огонь alien в зоне поражения ship """

if len(gbullets) < ai_settings.gbullets_allowed:

   for alien in aliens:

       for ship in m_ships:

           if (alien.rect.x > ship.zonx_min) and (alien.rect.x < ship.zonx_max):

               new_gbullet = Gbullet(ai_settings, screen, alien)

               gbullets.add(new_gbullet)

               shoot_sound5.play() ##

               sleep(0.3)      ##

               ship.aliene_fight = False

 

 

def update_screen(ai_settings, screen, stats, sb, m_ships, aliens, bullets,

   gbullets, play_button):

"""Update images on the screen, and flip to the new screen."""

# Redraw the screen, только один раз для удаления кнопки

if stats.game_button_pressed:

   screen.blit(bgr_img, (0, 0))

   stats.game_button_pressed = False

 

bullets.draw(screen)

gbullets.draw(screen)

 

m_ships.clear(screen, bgr_img)  

m_ships.draw(screen)

   

aliens.clear(screen, bgr_img) 

aliens.draw(screen)

   

# Draw the score information.

sb.show_score()

   

# Draw the play button if the game is inactive.

if not stats.game_active:

   play_button.draw_button()

 

# Make the most recently drawn screen visible.

pygame.display.flip()

   

def update_bullets(ai_settings, screen, stats, sb, m_ships, aliens, bullets):

"""Update position of bullets, and get rid of old bullets."""

# Update bullet positions.

bullets.update()

 

# Get rid of bullets that have disappeared.

for bullet in bullets.copy():

   if bullet.rect.bottom <= 0:

       bullets.remove(bullet)

           

check_bullet_alien_collisions(ai_settings, screen, stats, sb, m_ships,

   aliens, bullets)

 

def update_gbullets(ai_settings, screen, stats, sb, m_ships, aliens,

               gbullets):

"""Update position of bullets, and get rid of old bullets."""

# Update gbullet positions.

gbullets.update()

 

# Get rid of bullets that have disappeared.

for gbullet in gbullets.copy():

   if gbullet.rect.bottom >= ai_settings.screen_height:

       gbullets.remove(gbullet)

           

#check_g_bullet_ship_collisions(ai_settings, screen, stats, sb, ship,

# aliens, g_bullets)

 

 

def update_ships(m_ships):

""" обновление Group m_ships """

for ship in m_ships:

   ship.update()

 

       

def check_high_score(stats, sb):

"""Check to see if there's a new high score."""

if stats.score > stats.high_score:

   stats.high_score = stats.score

   sb.prep_high_score()

           

def check_bullet_alien_collisions(ai_settings, screen, stats, sb, m_ships,

                             aliens, bullets):

"""Respond to bullet-alien collisions."""

# Remove any bullets and aliens that have collided.

collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

   

if collisions:

   for aliens in collisions.values():

       stats.score += ai_settings.alien_points * len(aliens)

       sb.prep_score()

   check_high_score(stats, sb)

   shoot_sound3.play() ## звук попадания в противника

   

if len(aliens) == 0:

   # If the entire fleet is destroyed, start a new level.

   bullets.empty()

   ai_settings.increase_speed()

       

   # Increase level.

   stats.level += 1

   sb.prep_level()

       

   create_fleet(ai_settings, screen, aliens)

   

def check_fleet_edges(ai_settings, aliens):

"""Respond appropriately if any aliens have reached an edge."""

for alien in aliens.sprites():

   if alien.check_edges():

       change_fleet_direction(ai_settings, aliens)

       break

       

def change_fleet_direction(ai_settings, aliens):

"""Drop the entire fleet, and change the fleet's direction."""

for alien in aliens.sprites():

   alien.rect.y += ai_settings.fleet_drop_speed

ai_settings.fleet_direction *= -1

   

def ship_hit(ai_settings, screen, stats, sb, ship, m_ships, aliens, bullets):

"""Respond to ship being hit by alien."""

if stats.ships_left > 0:

   # Decrement ships_left.

   stats.ships_left -= 1       

   # Update scoreboard.

   sb.prep_ships()

       

else:

   stats.game_active = False

   pygame.mouse.set_visible(True)

   

# Empty the list of aliens and bullets.

aliens.empty()

bullets.empty()

# m_ships.empty()

   

# Create a new fleet, and center the ship.

create_fleet(ai_settings, screen, aliens)

ship.center_ship()

m_ships.add(ship)

   

# Pause.

sleep(0.5)

   

def check_aliens_bottom(ai_settings, screen, stats, sb, ship, m_ships, aliens,

   bullets):

"""Check if any aliens have reached the bottom of the screen."""

screen_rect = screen.get_rect()

for alien in aliens.sprites():

   if alien.rect.bottom >= screen_rect.bottom:

       stats.game_button_pressed = True  # для перезаписи полностью экрана (ships_left)

       # Treat this the same as if the ship got hit.

       ship_hit(ai_settings, screen, stats, sb, ship, m_ships, aliens, bullets)

       shoot_sound4.play() ## звук крушения корабля

       break

           

def update_aliens(ai_settings, screen, stats, sb, m_ships, aliens, bullets,

   gbullets):

"""

Check if the fleet is at an edge,

then update the postions of all aliens in the fleet.

"""

check_fleet_edges(ai_settings, aliens)

aliens.update()

# при флаге ответного огня начать стрелять противнику

for ship in m_ships :

   if ship.aliene_fight == True :

       fire_gbullet(ai_settings, screen, m_ships, bullets, aliens, gbullets)       

   

# Look for alien-ship collisions.

for ship in m_ships:

   if pygame.sprite.spritecollideany(ship, aliens):

       ship_hit(ai_settings, screen, stats, sb, ship, m_ships, aliens, bullets)

       shoot_sound4.play() ## звук крушения корабля

       stats.game_button_pressed = True # для перезаписи полностью экрана (ships_left)

   # Look for aliens hitting the bottom of the screen.

   check_aliens_bottom(ai_settings, screen, stats, sb, ship, m_ships, aliens, bullets)

           

def get_number_aliens_x(ai_settings, alien_width):

"""Determine the number of aliens that fit in a row."""

available_space_x = ai_settings.screen_width - 4 * alien_width ##

number_aliens_x = int(available_space_x / (6 * alien_width)) ##

return number_aliens_x

 

def create_alien(ai_settings, screen, aliens, alien_number, row_number):

"""Create an alien, and place it in the row."""

alien = Alien(ai_settings, screen)

alien_width = alien.rect.width

alien.x = 4*alien_width + 6 * alien_width * alien_number ##

alien.rect.x = alien.x

alien.rect.y = 2*alien.rect.height + 6 * alien.rect.height * row_number ##

aliens.add(alien)

 

def create_fleet(ai_settings, screen, aliens):

"""Create a full fleet of aliens."""

# Create an alien, and find number of aliens in a row.

alien = Alien(ai_settings, screen)

number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)

number_rows = int(1) # get_number_rows(ai_settings, ship.rect.height,

   # alien.rect.height)

   

# Create the fleet of aliens.

for row_number in range(number_rows):

   for alien_number in range(number_aliens_x):

       create_alien(ai_settings, screen, aliens, alien_number, row_number)

 

----------------------------------------------------------------------------------------------------------


































































































































Ship.py

 

import pygame

from pygame.sprite import Sprite

 

class Ship(Sprite):

 

def __init__(self, ai_settings, screen):

   """Initialize the ship, and set its starting position."""

   super(Ship, self).__init__()

   self.screen = screen

   self.ai_settings = ai_settings

 

   # Load the ship image, and get its rect.

   self.image = pygame.image.load('images/shooter.bmp')

   self.rect = self.image.get_rect()

   self.screen_rect = screen.get_rect()

 

   # Start each new ship at the bottom center of the screen.

   self.rect.centerx = self.screen_rect.centerx

   self.rect.bottom = self.screen_rect.bottom

       

   # Store a decimal value for the ship's center.

   self.center = float(self.rect.centerx)

       

   # Movement flags.

   self.moving_right = False

   self.moving_left = False

   # Добавим флаг разрешения на ответ враж. огонь

   self.aliene_fight = False

       

def center_ship(self):

   """Center the ship on the screen."""

   self.center = self.screen_rect.centerx

       

def update(self):

   """Update the ship's position, based on movement flags."""

   # Update the ship's center value, not the rect.

   if self.moving_right and self.rect.right < self.screen_rect.right:

       self.center += self.ai_settings.ship_speed_factor           

   if self.moving_left and self.rect.left > 0:

       self.center -= self.ai_settings.ship_speed_factor

   # определим зону вражеского обстрела ship (x_min и x_max)

   self.zonx_min = self.center - self.ai_settings.ship_zonx

   self.zonx_max = self.center + self.ai_settings.ship_zonx

 

   # Update rect object from self.center.

   self.rect.centerx = self.center

 

def blitme(self):

   """Draw the ship at its current location."""

   self.screen.blit(self.image, self.rect)

 

----------------------------------------------------------------------------------------------------------

Alien.py

 

import pygame

from pygame.sprite import Sprite

import myvar 

 

class Alien(Sprite):

"""A class to represent a single alien in the fleet."""

 

def __init__(self, ai_settings, screen):

   """Initialize the alien, and set its starting position."""

   super(Alien, self).__init__()

   self.screen = screen

   self.ai_settings = ai_settings

 

   # Load the alien image, and set its rect attribute.

   self.image = pygame.image.load('images/gans.bmp')

   self.rect = self.image.get_rect()

 

   # Start each new alien near the top left of the screen.

   self.rect.x = self.rect.width

   self.rect.y = self.rect.height

 

   # Store the alien's exact position.

   self.x = float(self.rect.x)

       

def check_edges(self):

   """Return True if alien is at edge of screen."""

    screen_rect = self.screen.get_rect()

   if self.rect.right >= screen_rect.right:

       return True

   elif self.rect.left <= 0:

       return True

       

def update(self):

   """Move the alien right or left."""

   self.x += (self.ai_settings.alien_speed_factor *

                   self.ai_settings.fleet_direction)

   self.rect.x = self.x

 

def blitme(self):

   """Draw the alien at its current location."""

   self.screen.blit(self.image, self.rect)

 

----------------------------------------------------------------------------------------------------------

Bullet.py

 

import pygame

from pygame.sprite import Sprite

 

class Bullet(Sprite):

"""A class to manage bullets fired from the ship."""

 

def __init__(self, ai_settings, screen, ship):

   """Create a bullet object, at the ship's current position."""

   super(Bullet, self).__init__()

   self.screen = screen

 

   # Load the bullit image, and set its rect attribute.

     self.image = pygame.image.load('images/bullet.bmp')

   self.rect = self.image.get_rect()

   self.rect.x = self.rect.width

   self.rect.y = self.rect.height

 

   # Create bullet rect at (0, 0), then set correct position.

   # self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,

   # ai_settings.bullet_height)

   self.rect.centerx = ship.rect.centerx

   self.rect.top = ship.rect.top

       

   # Store a decimal value for the bullet's position.

   self.y = float(self.rect.y)

 

   # self.color = ai_settings.bullet_color

   self.speed_factor = ai_settings.bullet_speed_factor

 

def update(self):

   """Move the bullet up the screen."""

   # Update the decimal position of the bullet.

   self.y -= self.speed_factor

   # Update the rect position.

   self.rect.y = self.y

 

def draw_bullet(self):

   """Draw the bullet to the screen."""

   # pygame.draw.rect(self.screen, self.color, self.rect)

 

   self.screen.blit(self.image, self.rect)

 

----------------------------------------------------------------------------------------------------------

Button.py

 

import pygame.font

 

class Button():

 

def __init__(self, ai_settings, screen, msg):

   """Initialize button attributes."""

   self.screen = screen

   self.screen_rect = screen.get_rect()

       

   # Set the dimensions and properties of the button.

   self.width, self.height = 200, 50

   self.button_color = (0, 255, 0)

   self.text_color = (255, 255, 255)

   self.font = pygame.font.SysFont(None, 48)

       

   # Build the button's rect object, and center it.

   self.rect = pygame.Rect(0, 0, self.width, self.height)

   self.rect.center = self.screen_rect.center

       

   # The button message only needs to be prepped once.

   self.prep_msg(msg)

 

def prep_msg(self, msg):

   """Turn msg into a rendered image, and center text on the button."""

   self.msg_image = self.font.render(msg, True, self.text_color,

       self.button_color)

   self.msg_image_rect = self.msg_image.get_rect()

   self.msg_image_rect.center = self.rect.center

       

def draw_button(self):

   # Draw blank button, then draw message.

   self.screen.fill(self.button_color, self.rect)

   self.screen.blit(self.msg_image, self.msg_image_rect)

 

----------------------------------------------------------------------------------------------------------

Settings.py

 

class Settings():

"""A class to store all settings for Alien Invasion."""

 

def __init__(self):

   """Initialize the game's static settings."""

   # Screen settings.

   self.screen_width = 1423 #1200

   self.screen_height = 800

  

   self.bg_color = (230, 230, 230)

       

   # Ship settings.

   self.ship_limit = 3

   # добавим размер зоны ответного враж. огня

   self.ship_zonx = 50

           

   # Bullet settings.

   self.bullet_width = 3

   self.bullet_height = 10 #15

   self.bullet_color = 60, 60, 60

   self.bullets_allowed = 3

   # Добавим колв-о ответного огня

   self.gbullets_allowed = 5

               

   # Alien settings.

   self.fleet_drop_speed = 10

           

   # How quickly the game speeds up.

   self.speedup_scale = 1.1

   # How quickly the alien point values increase.

   self.score_scale = 1.5

   

   self.initialize_dynamic_settings()

 

def initialize_dynamic_settings(self):

   """Initialize settings that change throughout the game."""

   self.ship_speed_factor = 1.5

   self.bullet_speed_factor = 2

   self.alien_speed_factor = 1

       

   # Scoring.

   self.alien_points = 50

   

   # fleet_direction of 1 represents right, -1 represents left.

   self.fleet_direction = 1

       

def increase_speed(self):

   """Increase speed settings and alien point values."""

   self.ship_speed_factor *= self.speedup_scale

   self.bullet_speed_factor *= self.speedup_scale

   self.alien_speed_factor *= self.speedup_scale

       

   self.alien_points = int(self.alien_points * self.score_scale)

 

----------------------------------------------------------------------------------------------------------

game_stats.py

 

class GameStats():

"""Track statistics for Alien Invasion."""

   

def __init__(self, ai_settings):

   """Initialize statistics."""

   self.ai_settings = ai_settings

   self.reset_stats()

       

   # Start game in an inactive state.

   self.game_active = False

   self.game_button_pressed = False

       

   # High score should never be reset.

   self.high_score = 0

       

def reset_stats(self):

   """Initialize statistics that can change during the game."""

   self.ships_left = self.ai_settings.ship_limit

   self.score = 0

   self.level = 1

 

----------------------------------------------------------------------------------------------------------

Scoreboard.py

 

import pygame.font

from pygame.sprite import Group

 

from ship import Ship

 

class Scoreboard():

"""A class to report scoring information."""

 

def __init__(self, ai_settings, screen, stats):

   """Initialize scorekeeping attributes."""

   self.screen = screen

   self.screen_rect = screen.get_rect()

   self.ai_settings = ai_settings

   self.stats = stats

       

   # Font settings for scoring information.

   self.text_color = (30, 30, 30)

   self.font = pygame.font.SysFont(None, 48)

 

   # Prepare the initial score images.

   self.prep_score()

   self.prep_high_score()

   self.prep_level()

   self.prep_ships()

 

def prep_score(self):

   """Turn the score into a rendered image."""

   rounded_score = int(round(self.stats.score, -1))

   score_str = "{:,}".format(rounded_score)

   self.score_image = self.font.render(score_str, True, self.text_color,

       self.ai_settings.bg_color)

           

   # Display the score at the top right of the screen.

   self.score_rect = self.score_image.get_rect()

   self.score_rect.right = self.screen_rect.right - 20

   self.score_rect.top = 20

       

def prep_high_score(self):

   """Turn the high score into a rendered image."""

   high_score = int(round(self.stats.high_score, -1))

   high_score_str = "{:,}".format(high_score)

   self.high_score_image = self.font.render(high_score_str, True,

       self.text_color, self.ai_settings.bg_color)

               

   # Center the high score at the top of the screen.

   self.high_score_rect = self.high_score_image.get_rect()

      self.high_score_rect.centerx = self.screen_rect.centerx

   self.high_score_rect.top = self.score_rect.top

       

def prep_level(self):

   """Turn the level into a rendered image."""

   self.level_image = self.font.render(str(self.stats.level), True,

           self.text_color, self.ai_settings.bg_color)

       

   # Position the level below the score.

   self.level_rect = self.level_image.get_rect()

   self.level_rect.right = self.score_rect.right

   self.level_rect.top = self.score_rect.bottom + 10

       

def prep_ships(self):

   """Show how many ships are left."""

   self.ships = Group()

   for ship_number in range(self.stats.ships_left):

       ship = Ship(self.ai_settings, self.screen)

       ship.rect.x = 10 + ship_number * ship.rect.width

       ship.rect.y = 10

       self.ships.add(ship)

       

def show_score(self):

   """Draw score to the screen."""

   self.screen.blit(self.score_image, self.score_rect)

   self.screen.blit(self.high_score_image, self.high_score_rect)

   self.screen.blit(self.level_image, self.level_rect)

   # Draw ships.

   self.ships.draw(self.screen)

 

----------------------------------------------------------------------------------------------------------

Myvar.py

 

import pygame

 

my_image = pygame.image.load('images/land.bmp')

 

 

----------------------------------------------------------------------------------------------------------

Gbullet.py

 

 

import pygame

from pygame.sprite import Sprite

 

class Gbullet(Sprite):

"""A class to manage bullets fired from the alien."""

 

def __init__(self, ai_settings, screen, alien):

   """Create a bullet object, at the ship's current position."""

    super(Gbullet, self).__init__()

   self.screen = screen

 

   # Load the bullit image, and set its rect attribute.

   self.image = pygame.image.load('images/bullet.bmp')

   self.rect = self.image.get_rect()

   self.rect.x = self.rect.width

   self.rect.y = self.rect.height

 

   # Create bullet rect at (0, 0), then set correct position.

   # self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,

   # ai_settings.bullet_height)

   self.rect.centerx = alien.rect.centerx

   self.rect.top = alien.rect.top

       

   # Store a decimal value for the bullet's position.

   self.y = float(self.rect.y)

 

   # self.color = ai_settings.bullet_color

   self.speed_factor = ai_settings.bullet_speed_factor

 

def update(self):

   """Move the bullet down the screen."""

   # Update the decimal position of the bullet.

   self.y += self.speed_factor

   # Update the rect position.

   self.rect.y = self.y

 

def draw_bullet(self):

   """Draw the bullet to the screen."""

   # pygame.draw.rect(self.screen, self.color, self.rect)

 

   self.screen.blit(self.image, self.rect)

 

****************************************************************

Лаб_7 - Подключение, USB передача сигналов сигналов трехкоординатного датчика с АЦП на PC осциллограф (Питон).

В качестве трехкоординатного датчика подключенного к Arduino используем три потенциометра подключенных по схеме приведенной в Лаб 4.( п.п. 4.2), при этом средний вывод потенциометров подключены соответственно к АЦП входам A0, A1, A2 соответственно. Передача данных переменных напряжений с потенциометров X,Y,Z по COM каналу связи на РС осуществляется в пакетном режиме.

Код Arduino:

#define PIN_LED 11
#define PIN_X A0
#define PIN_Y A1
#define PIN_Z A2
#define PIN_SOUND 3

int analogVal_X = 0;
int analogVal_Y = 0;
int analogVal_Z = 0;
int brightn = 0;

void setup() {

pinMode(PIN_LED, OUTPUT);
pinMode(PIN_X, INPUT);
pinMode(PIN_Y, INPUT);
pinMode(PIN_Z, INPUT);
pinMode(PIN_SOUND, OUTPUT);

Serial.begin(19200);

}

void loop() {

delay(200);
  analogVal_X = analogRead(PIN_X);
analogVal_Y = analogRead(PIN_Y);
analogVal_Z = analogRead(PIN_Z);
brightn = analogVal_X/4;
analogWrite(PIN_LED, brightn);

 

Serial.print(analogVal_X);
Serial.print(" ");
Serial.print(analogVal_Y);
Serial.print(" ");
Serial.print(analogVal_Z);
Serial.print("\n");

analogWrite(PIN_SOUND, 50);
delay(100);
analogWrite(PIN_SOUND, 0);

delay(200);

}

Для приема, визуализации, записи в файл получаемых на PC от Arduino данных напишем на Python программу.   

GUI программы приема и обработки данных

 

Код программа (serial_monitor&plot_tkinter_val3_TKinter_07.py ):

from serial import *

from tkinter import *

from tkinter import messagebox

from tkinter.filedialog import *

import fileinput

 

serialPort = "COM3" # ИЗМЕНИТЬ НА НОМЕР ИСПОЛЬЗУЕМОГО COM ПОРТА!!!

baudRate = 9600

ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0)

 

#make a TkInter Window

root = Tk()

root.wm_title("Reading Serial")

 

# строчные переменные для строчных потоков данных порта и

# окрытого файла 

ComStrData = ""

FileStrData = ""

 

#make our own buffer

serBuffer = ""

FileStrBuff = ""

# битовая переменная чтения данных из порта

dd = b"a"

# переменная текущего количества принятых строк данных XYZ

DStrNum = 0

FStrNum = 0

# переменная стартового номера строки для анимационного (онлайн) графика 

LGraph_StartStrNum = 0

 

StartMode = False

ContinueStartMode = False

LiveGraphMode = False

 

# массивы для получаемых данных COM порта

comX = []

comY = []

comZ = []

# массивы для данных открытого файла

fopX = []

fopY = []

fopZ = []

 

# переменная индикации графика данных - com(TRUE) file(False)

ComFile_PlotMod = True 

 

# создаем надписи и окна индкации GUI программы  

label_ComDataXYZ = Label(root, text="ComXYZ ", font='Arial 8')

label_ComStrNum = Label(root, text="CStrNum -", font='Arial 8')

label_FileStrNum = Label(root, text="FStrNum -", font='Arial 8')

label_SaveFNote = Label(root, text="SaveFNote -", font='Arial 8')

label_OpenFNote = Label(root, text="OpenFNote -", font='Arial 8')

 

txt_DataStr = Text(root, height=32, takefocus=0)

txt_X = Text(root, height=1, font='Arial 14', takefocus=0)

txt_Y = Text(root, height=1, font='Arial 14', takefocus=0)

txt_Z = Text(root, height=1, font='Arial 14', takefocus=0)

txt_N = Text(root, height=1, font='Arial 14', takefocus=0)

txt_FileStrN = Text(root, height=1, font='Arial 14', \

          takefocus=0)

 

txt_SaveFNote = Text(root, height=2, font='Arial 8', \

          takefocus=0)

txt_OpenFNote = Text(root, height=2, font='Arial 8', \

          takefocus=0)

 

def FnStopWarningMsg():

messagebox.showwarning("Предупреждение", "Нужно остановить чтение порта (кн.STOP)")

def FnStartWarningMsg():

messagebox.showwarning("Предупреждение", "Нужно запустить чтение порта (кн.START)")

 

# Функ инициализации запуска процесса чтения из сериал порта  

def FnButStart():

global StartMode

global ContinueStartMode

global DStrNum

global serBuffer

global comX, comY, comZ

# если ранее не установлен режима старта чтения из порта

# включаем флаги и стартовая инициализация переменных

if StartMode == False:

   StartMode = True

   ContinueStartMode = False

   DStrNum = 0

   txt_N.delete('0.0', END)

   txt_N.insert('0.0', DStrNum)

   ComStrData = ""

   serBuffer = ""

   txt_DataStr.delete('0.0',END)

   comX = []

   comY = []

   comZ = []   

 

# Функ остановки процесса чтения из сериал порта

def FnButStop():

global StartMode

# выключаем режим старта чтения из порта

if StartMode == True:

   StartMode = False

 

# Функ продолжения процесса чтения из сериал порта

def FnButContinue():

global StartMode

global ContinueStartMode

global ComStrData

# включаем режим старта без стартовой инициализации переменных

if StartMode == False:

   StartMode = True

   ContinueStartMode = True

       

# Функ сохранения в файл сериал данных

def FnButSAVE_FILE():

global StartMode

global ComStrData

#предупреждаем и выходим если идет чтение из порта

if StartMode == True:

   FnStopWarningMsg()

   return

sa = asksaveasfilename()

f = open(sa,"w")

f.write(ComStrData)

f.close()

 

# Функ чтения из файла ранее сохраненных сериал данных

def FnButOPEN_FILE():

global StartMode

global FileStrData

global fopX, fopY, fopZ

global FileStrBuff

global FStrNum

#предупреждаем и выходим если идет чтение из порта

if StartMode == True:

   FnStopWarningMsg()

   return

# читаем данные из файла и обрабатываем

FileStrBuff = ""

FStrNum = 0

op = askopenfilename()

FileStrData = ""

txt_DataStr.delete('0.0', END)       

for FileStrData in fileinput.input(op):

   txt_DataStr.insert('0.0', FileStrData)

   OpnFileData_list = list(map(int, FileStrData.split(' ')))

   fopX.append(OpnFileData_list[0])

   fopY.append(OpnFileData_list[1])

   fopZ.append(OpnFileData_list[2])

   FileStrData = ""

   FStrNum += 1

txt_FileStrN.delete('0.0', END)

txt_FileStrN.insert('0.0', FStrNum)

 

# Функ рисования осей O_X и O_Y координат для plot canvas (1008x520)

def PlotAxis():

plot.create_line(8,520,8,4, # ось O_Y (вертикал)

plot.create_line(4,518,1004,518,# ось O_X (горизонт)

 

   

# Функ графического отображения сериал данных полученных из порта

def FnButDATA_GRAPH():

global StartMode

global FStrNum

#предупреждаем и выходим если идет чтение из порта

if StartMode == True:

   FnStopWarningMsg()

   return

GraphPlot()

   

# Функ графического отображения сериал данных полученных из файла 

def FnButFILE_GRAPH():

global StartMode

 #предупреждаем и выходим если идет чтение из порта

if StartMode == True:

   FnStopWarningMsg()

   return

 

def FnButLIVE_GRAPH():

global StartMode, LiveGraphMode

# предупреждаем и выходим если не запущено чтение из порта (START)

if StartMode == False:

   FnStartWarningMsg()

   return

# если режим анимации не установлен, то запускаем, иначе останавливаем

# режим анимации графика

if LiveGraphMode == False:

   LiveGraphMode = True

else:

   LiveGraphMode = False

plot.delete("all")

PlotAxis()

 

# создаем управляющие элементы GUI программы   

plot = Canvas(root, width = 1008, height = 520, bg = "lightblue")

button1_START = Button(root, text='START', height=1, \

                 font='Arial 10', command=FnButStart)

button2_STOP = Button(root, text='STOP', height=1, \

                 font='Arial 10', command=FnButStop)

button3_CONTINUE = Button(root, text='CONTINUE', \

            height=1, font='Arial 10', command=FnButContinue)

button4_SAVE_FILE = Button(root, text='SAVE_FILE', \

        height=1, font='Arial 10', command=FnButSAVE_FILE)

button5_OPEN_FILE = Button(root, text='OPEN_FILE', \

        height=1, font='Arial 10', command=FnButOPEN_FILE)

button6_DATA_GRAPH = Button(root, text='COM_GRAPH', \

        height=1, font='Arial 10', command=FnButDATA_GRAPH)

button7_FILE_GRAPH = Button(root, text='FILE_GRAPH', \

        height=1, font='Arial 10', command=FnButFILE_GRAPH)

button8_LIVE_GRAPH = Button(root, text='LIVE_GRAPH', \

        height=1, font='Arial 10', command=FnButLIVE_GRAPH)

 

# make a scrollbar

scrollbar = Scrollbar(root, orient=VERTICAL)

 

# через grid размещаем элементы GUI в главном окне 

scrollbar.grid(row=1, column=0,columnspan = 1, sticky='ns', rowspan = 3)

# размещаем окна входных данных порта

label_ComDataXYZ.grid(row=0, column=0)

txt_X.grid(row=0, column=1)

txt_Y.grid(row=0, column=2)

txt_Z.grid(row=0, column=3)

# размещаем окно числа принятых строк

label_ComStrNum.grid(row=0, column=4)

txt_N.grid(row=0, column=5)

# размещаем окно индикации принятых строк и окно графика

txt_DataStr.grid(row=1, column=1,columnspan = 3)

plot.grid(row=1, column=4,columnspan = 12, rowspan = 2)

# размещаем кнопки управелния процессами

button1_START.grid(row=0, column=6)

button2_STOP.grid(row=0, column=7)

button3_CONTINUE.grid(row=0, column=8)

button4_SAVE_FILE.grid(row=0, column=9)

label_FileStrNum.grid(row=0, column=10)

txt_FileStrN.grid(row=0, column=11)

button5_OPEN_FILE.grid(row=0, column=12)

button6_DATA_GRAPH.grid(row=0, column=13)

button7_FILE_GRAPH.grid(row=0, column=14)

button8_LIVE_GRAPH.grid(row=0, column=15)

# размещаем окна примечаний для записываемомго и считанного файла

label_SaveFNote.grid(row=3, column=2)

txt_SaveFNote.grid(row=3, column=3, columnspan = 12)

label_OpenFNote.grid(row=4, column=2)

txt_OpenFNote.grid(row=4, column=3, columnspan = 12)

 

# attach text box to scrollbar

txt_DataStr.config(yscrollcommand=scrollbar.set)

scrollbar.config(command=txt_DataStr.yview)

 

# Функ воспроизведения статической графика

def GraphPlot():

global DStrNum

if ComFile_PlotMod == True:

   for i in range(2, 125):

       if i < DStrNum:

           px = 8+(i-1)*5

           pyX = 520 - comX[i-1]//2

           pyY = 520 - comY[i-1]//2

           pyZ = 520 - comZ[i-1]//2

 

           px_ = 8+i*5

           pyX_ = 520 - comX[i]//2

           pyY_ = 520 - comY[i]//2

           pyZ_ = 520 - comZ[i]//2

 

           plot.create_line(px,pyX,px_,pyX_,= 'black')

           plot.create_line(px,pyY,px_,pyY_,= 'red')

           plot.create_line(px,pyZ,px_,pyZ_,= 'blue')

               

       else:

           break

 

# Функ воспроизведения анимированной (онлайн) графика

def LiveGraphPlot():

global DStrNum, LGraph_StartStrNum

if LGraph_StartStrNum == 0:

   LGraph_StartStrNum = DStrNum

   index = 1

if ComFile_PlotMod == True:

   for i in range(2, 125):

       if i < DStrNum:

           px = 8+(i-1)*5

           pyX = 520 - comX[i-1+LGraph_StartStrNum]//2

           pyY = 520 - comY[i-1+LGraph_StartStrNum]//2

           pyZ = 520 - comZ[i-1+LGraph_StartStrNum]//2

 

           px_ = 8+i*5

           pyX_ = 520 - comX[i+LGraph_StartStrNum]//2

           pyY_ = 520 - comY[i+LGraph_StartStrNum]//2

           pyZ_ = 520 - comZ[i+LGraph_StartStrNum]//2

 

           plot.create_line(px,pyX,px_,pyX_,= 'black')

           plot.create_line(px,pyY,px_,pyY_,= 'red')

           plot.create_line(px,pyZ,px_,pyZ_,= 'blue')

               

       else:

           break

   # увеличиваем индекс воспроизводимого количества данных с начала

   # анимации но не более макс размерности графика по O_X (1000/шаг индикации)

   index += 1

        

# ФУНКЦИЯ чтения из сериал (COM_N) порта строчные данные и воспроизводим

# данные в индикаторных окнах

def readSerial():

while True:

   dd = ser.read() # attempt to read a character from Serial

   c=dd.decode("utf-8")

   #was anything read?

   if len(c) == 0:

       break

   # get the buffer from outside of this function

   global ComStrData

   global serBuffer

   global DStrNum

   global StartMode

   global comX, comY, comZ

   # после буферного набора данных очередной строки из строчного потока данных                  

   if c == '\n':

       serBuffer += "\n" # add the newline to the buffer

       # читаем из строки данных отдельные числа X,Y,Z                   

       numbers_list = list(map(int, serBuffer.split(' ')))

       X=numbers_list[0]

       Y=numbers_list[1]

       Z=numbers_list[2]

       DStrNum += 1

       comX.append(X)

       comY.append(Y)

       comZ.append(Z)           

       # перепишем полученные данные в соответствующие окна X,Y,Z

       txt_X.delete('0.0', END)

       txt_X.insert('0.0', X)

       txt_Y.delete('0.0', END)

       txt_Y.insert('0.0', Y)

       txt_Z.delete('0.0', END)

       txt_Z.insert('0.0', Z)

           

       if StartMode == True:

           #add the line to the TOP of the log

           txt_DataStr.insert('0.0', serBuffer)

           txt_N.delete('0.0', END)

           txt_N.insert('0.0', DStrNum)

           ComStrData += serBuffer

 

       if LiveGraphMode == True:

           plot.delete("all")

           PlotAxis()

           LiveGraphPlot()       

 

       serBuffer = "" # empty the buffer

   else: # набираем в буфер данные текущей отдельной строки(до символа \n)

       serBuffer += c # add to the buffer

root.after(10, readSerial) # check serial again soon

 

# пропишем в окна начальные значения переменных 

txt_N.delete('0.0', END)

txt_N.insert('0.0', DStrNum)

txt_FileStrN.delete('0.0', END)

txt_FileStrN.insert('0.0', FStrNum)

 

# Рисуем оси координат для plot canvas (1008x520)

PlotAxis()

# plot.create_line(8,520,8,4, # ось O_Y (вертикал)

# plot.create_line(4,518,1004,518,# ось O_X (горизонт)

 

# after initializing serial, an arduino may need a bit of time to reset

root.after(100, readSerial)

 

root.mainloop()

 

****************************************************************

Лаб_8 - Подключение, USB передача сигналов звукового модуля на PC осциллограф (Питон).

 

****************************************************************

Лаб_9 - Конфигурирование и программирование ультразвуковой системы измерения расстояния.

 

****************************************************************

Лаб_10 - Конфигурирование и программирование ультразвуковой системы измерения расстояния.

 


****************************************************************

Лаб_10 - Конфигурирование и программирование робокара

 

****************************************************************

Лаб_11 - Конфигурирование и программирование робокара

 

****************************************************************

Лаб_12 - Конфигурирование и программирование робота манипулятора

 

****************************************************************

Лаб_13 - Конфигурирование и программирование робота манипулятора

 

 

****************************************************************

Лаб_14 - Конфигурирование и программирование Интернет сети.

 

****************************************************************

Лаб_15 - Конфигурирование и программирование Интернет сети.

 

 

****************************************************************

 

****************************************************************

Приложение 1.
Устройство платы Arduino Uno R3

Плата Arduino Uno — центр большой империи Arduino, самое популярное и самое доступное устройство Arduino. В ее основе лежит чип ATmega — в последней ревизии Arduino Uno R3 это ATmega328 (хотя на рынке можно еще встретить варианты платы UNO с ATmega168). Arduino Uno является самым подходящим вариантом для начала работы с платформой: она имеет удобный размер (не слишком большой, как у Mega и не такой маленький, как у Nano), достаточно доступна из-за массового выпуска всевозможных клонов, под нее написано огромное количество бесплатных уроков и скетчей. В этой статье мы рассмотрим основные особенности, характеристики и устройство платы Arduino Uno R3, требования к питанию и возможности подключения внешних устройств.

1 Характеристики Arduino Uno R3

2 Изображения плат Ардуино Уно

3 Устройство Arduino Uno

3.1 Схема платы Arduino Uno

3.2 Описание элементов платы Arduino Uno R3

3.3 Распиновка микроконтроллера ATMega 328

4 Описание пинов Ардуино

4.1 Цифровые пины Arduino Uno

4.2 Аналоговые пины Arduino Uno

4.3 Дополнительные разъемы

5 Варианты питания Ардуино Уно

6 Память Arduino Uno R3

7 Отличие Arduino Uno от других плат

7.1 Отличия Arduino Uno от Arduino Nano

8 Краткие выводы


























Дата: 2019-05-28, просмотров: 217.