Форум сайта python.su
Всем привет. Меня всё интересует поучающий код - Robot.py(где надо довести квадратик к цели). Считаю,что пока не разберёшся хотя-бы с одной программкой,пока не поймёш весь смысл,вложенный в коде,не стоит и переходить к другим вопросам по Питону.Вообщем логику,классы,смысл я понял этого кода,. В частности меня интересует такие вопросы:
1) def redraw(rect): что в этой функции управления прорисовкой значит rect ? Когда он(rect) вызывается?
2) if canvas:
canvas.blit(img) - как это понять?(Если обновился экран,то на этот экран вывести img ?). Меня интересует смысл этих двух выражений: if canvas
Или как надо понимать?(.......................................................................................)
Офлайн
1. Вызывается периодически UI сервером, когда нужно перерисовать экран. В аргумент rect попадает тьюпл с областью экрана, который нужно перерисовать. Но дополнительно эту функцию обычно вызывают вручную, чтоб перерисовать принудительно.
2. Тут без всего кода трудно сказать, зачем автор так сделал. (до app.body=canvas, redraw все равно вызываться не будет)
Офлайн
Смотрю на “некоторые” задаваемые вопросы “Новичков”(хотя я пока и сам вникающий),аж самому сейчас становится и стыдно и “смешно”,что я даже этого недавно не знал(допустим мне как начинающему очччччччччччччень помогло во вникание в классы перегрузка встроенных оперов:допустим метод в классе:
cl...
def __str__(s):
(и тут можно дать задание (Уважаемому Питону) вывести какое хочеш выражение)
s.spam='hello frends'
return s.spam (это если через print s. А если __str__ заменить на __repr__,то можно вывести без print - экз-р---s(self)"Enter"
Офлайн
Вот небольшой код этой проги.Так можно? немного поподробней на вышеперечисленные вопросы
from graphics import *
from vibra import *
import appuifw as ui
import e32
##### Class
class cl_robot:
def __init__(self,x=1,y=1,exit_x=17,exit_y=17):
self.x=x
self.y=y
self.k=0
self.exit_x=exit_x
self.exit_y=exit_y
#--------------
def show(self,show=1):
# получаем глобальный объект "рисунок" на котором будет изображено положение Робота
global img
# задаём цвет рисования Робота
if show==1: color=0xffffff
else: color=0x0
# рисуем (или стираем) текущее положение Робота
img.rectangle(((self.x-1)*10+2,(self.y-1)*10+2,self.x*10-2,self.y*10-2),color,color)
# выводим в нижней части экрана количество шагов, которые уже сделал Робот
img.rectangle((5,180,100,190),0,0)
img.text((5,190),u'step=%s'%self.k,0xffffff)
#--------------
def step(self,d): #если d= 0 - шаг вправо, 1 - шаг вверх, 2 - шаг влево, 3 - шаг вниз
# run - это глобальный флаг, который будет отвечать за достижение цели (произойдёт останов программы)
global img,run
# рисуем чёрный квадрат на том месте, где раньше был наш Робот
self.show(0)
# это флаг, отвечающий за возможность сделать шаг в направлении d (True - можно, False - нельзя, упёрлись в стенку)
res=True
# проверяем, может ли Робот слелать шаг вправо.
if d==0:
# если может, то делаем этот шаг
if self.x<17: self.x+=1
# если не может - "сбрасываем" флаг
else: res=False
# далее - аналогично для направления "вверх", "влево", "вниз"
elif d==1:
if self.y>1: self.y-=1
else: res=False
elif d==2:
if self.x>1: self.x-=1
else: res=False
elif d==3:
if self.y<17: self.y+=1
else: res=False
# если шаг не был сделан - включаем вибру на 25 миллисекунд
if not res: vibrate(25,100)
# если шаг сделан - увеличиваем счётчик шагов Робота
else: self.k+=1
# проверяем достижение Цели
if (self.exit_x==self.x) and (self.exit_y==self.y):
# вывод сообщения о победе
ui.note(u'You win!!!')
# победная вибра :)
vibrate(100,100)
e32.ao_sleep(0.2)
vibrate(100,100)
e32.ao_sleep(0.2)
vibrate(100,100)
e32.ao_sleep(0.2)
vibrate(700,100)
e32.ao_sleep(0.2)
# цель достигнута! сбрасываем флаг
run=0
# рисуем Робота на новом месте (или на старом, если шаг не сделан)
self.show()
##### Class
# процедура, которая осуществляет завершение скрипта
def exit():
global run,script_lock,scr
run=0
# восстановим вид экрана, как до запуска скрипта
ui.app.screen=scr
script_lock.signal()
# инициализация "канвы"
canvas=None
# функция управления прорисовкой поля, Робота и всего, что будет на экране
def redraw(rect):
global canvas, img, robot
img.clear(0x0)
# рисуем сетку
for i in range (9,161,10):
img.line((0,i,171,i),0x555555)
img.line((i,0,i,171),0x555555)
# и поле
img.rectangle((0,0,171,171),0xffffff)
# рисуем Цель робота
img.rectangle(((robot.exit_x-1)*10+1,(robot.exit_y-1)*10+1,robot.exit_x*10-1,robot.exit_y*10-1),0xff0000,0xff0000)
# вывод поясняющей подсказки
img.text((160,203),u'Exit',0xff0000,u'LatinBold12')
# рисуем Робота
robot.show()
# так надо! :)
if canvas:
# выводим содержимое рисунка "img" на канву
canvas.blit(img)
# функция обработки нажатия клавиш
def event(event):
global robot,run
# вот тут-то и пригодился наш флаг. если флаг run=0, то реагировать на клавиши больше не надо, просто выходим из функции
if run==0: return False
# проверяем, какая кнопка нажата и действуем!
if event['keycode']==63495: robot.step(2)
elif event['keycode']==63496: robot.step(0)
elif event['keycode']==63497: robot.step(1)
elif event['keycode']==63498: robot.step(3)
# после нажатой клавиши надо перерисовать поле
redraw(0)
### ОСНОВНАЯ ПРОГРАММА
# запоминаем вид экрана до запуска скрипта и потом задаём вид "полный без кнопок и заголовка"
scr=ui.app.screen
ui.app.screen='full'
# сообщаем скрипту, как реагировать на нажатие правой софт-клавиши
ui.app.exit_key_handler=exit
# инициализация флага достижения цели. 1 - Цель не достигнута
run=1
# создаём экземпляр класса роботы - объект "Робот" и задаём начальные параметры. С днём рождения, Робот! :)
robot=cl_robot(2,12,17,1)
# создаём объект "рисунок" на котором мы будем рисовать всё
img=Image.new((176,208))
# указываем скрипту, что будем работать с графикой и назначаем процедуры, ответственные за прорисовку экрана (redraw_callback) и обработку нажатий клавиш (event_callback)
ui.app.body=canvas=ui.Canvas(event_callback=event,redraw_callback=redraw)
# первоначальная прорисовка экрана
redraw(canvas.size)
# заставляем скрипт ждать, пока его не закроют программно
script_lock=e32.Ao_lock()
script_lock.wait()
Офлайн
Мда, видно что код написан как раз таки новичком. Обилие global это очень плохой тон. if canvas и “инициализация канвы” canvas=None, вообще непонятно зачем было сделано.
Все можно было сделать в классе cl_robot без применения глобальных переменных.
Офлайн
1. Вызывается периодически UI серверомЧто такое UI сервер? И как понять “В аргумент rect попадает тьюпл с областью экрана”.Что такое тьюпл?
import appuifw, graphics, e32, key_codes
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
key_down = None
clicked = None
def handle_event(event):
global clicked, key_down
if event['type'] == appuifw.EEventKey:
if key_down:
key_down = (event['keycode'], "down")
else:
key_down = (event['keycode'], "pressed")
elif event['type'] == appuifw.EEventKeyUp and key_down:
code, mode = key_down
if mode == "pressed":
clicked = code
key_down = None
def key_is_down(code):
if key_down == (code, "down"):
return True
return False
def quit():
global running
running = False
def handle_redraw(rect): - rect.Когда он вызывается?
if img: canvas.blit(img) - вот ещё пример if img: как это понять?Напишите семантику этого выражения!
img = None
canvas = appuifw.Canvas(event_callback=handle_event,
redraw_callback=handle_redraw)
appuifw.app.screen = 'full'
appuifw.app.body = canvas
appuifw.app.exit_key_handler = quit
x = y = 100
w, h = canvas.size
img = graphics.Image.new((w, h))
img.clear(WHITE)
running = True
while running:
if key_is_down(key_codes.EKeyLeftArrow):
x -= 2
elif key_is_down(key_codes.EKeyRightArrow):
x += 2
elif key_is_down(key_codes.EKeyDownArrow):
y += 2
elif key_is_down(key_codes.EKeyUpArrow):
y -= 2
img.clear(WHITE)
img.point((x, y), outline = BLACK, width = 50)
handle_redraw(None) - Почему (None) ?
e32.ao_yield()
Офлайн
python4ikпрограммный компонент симбиана, который отвечает за работу с графическим интерфейсом.
Что такое UI сервер?
python4ikтьюпл он же tuple - встроенный тип http://docs.python.org/tutorial/datastructures.html
И как понять “В аргумент rect попадает тьюпл с областью экрана”.Что такое тьюпл?
python4ikесли img не None тогда выводим img на экран. Это сделано на тот случай, если img “не успелось” присвоится изображение. Но это тоже достаточно глупо. Легче сначала создать изображение, а потом гарантированно его использовать.
вот ещё пример if img: как это понять?
Офлайн
Если тьюпл это кортеж,то про кортеж я конечно знаю что это. :)
Вызывается периодически UI сервером, когда нужно перерисовать экран. В аргумент rect попадает тьюпл с областью экрана, который нужно перерисовать. Но дополнительно эту функцию обычно вызывают вручную, чтоб перерисовать принудительно.Допустим размер экрана (176,208). (х,у): (x-это коорд-ты точки по горизонтали,где она находится в данный момент,y-тоже самое(но по вертикали))
Отредактировано (Март 24, 2010 20:17:35)
Офлайн
В rect попадает координаты участка экрана, который после какие либо событий нужно перерисовать.
Допустим, на экран поверх всего вылезло note, после этого, участок экрана,где был этот note нужно обновить. Ну не запомнил UI сервер что там было под note :) , и он вызывает функцию redraw с параметром rect, куда попадает тьюпл с областью экрана, который желательно обновить. Но многие забивают на это и обновляют весь экран полностью.
python4ikА если логически подумать…. ?! Например, нажал ты на кнопку, положение спрайта изменилось, надо же экран перерисовать а не ждать, пока это сделает UI сервер, вызвав redraw.
И как,зачем вызывают функцию вручную,чтобы перерисовать принудительно?
Офлайн
Игорь я согласен,что Лутца мало для начала.Надо много-много учить и печатать.А так-как я с английским не совсем дружу,пару статей полезных на русском можно? Ссылку для начинающих про UI сервер и про перерисовку экрана! Я конечно ищу,но совет бы не помешал! Мне даже уже в последнее время жена говорит,когда я к ней подойду за целый день из своего офиса(компьютерной комнаты),а понимает моё увлечение Питоном! :) Учу!
Отредактировано (Март 25, 2010 17:54:34)
Офлайн