воскресенье, 11 октября 2009 г.

О совершенно посторонних библиотеках

Несколько постов подряд я пытаюсь показать, как можно использовать Blender не по назначению. Я стараюсь показать, что Blender так же является мощной средой программирования. Получилось мне это показать? Может, и да. Но лично я бы не поверил в то, что Blender можно использовать как независимую студию программирования, пусть даже на динамично развивающемся языке Python, если каждый рабочий скрипт начинается с такой строчки: import Blender. Подозрительно как-то, Вы не находите? Вот нашел. Итак, мы имеем скрипт, переворачивающий число – записывающий последовательность цифр в обратном порядке, если хотите. Вообще, любую самую тривиальную задачу можно сформулировать очень и очень красиво, но суть данного поста вот в чем – ответить на вопрос, возможно ли использовать Blender, как полноценная студия программирования, но при этом не использовать библиотеку Blender. Все это надо, чтобы в корне отсечь, возможности оппонента говорить, что без библиотеке Blender (import Blender) Blender (уже редактор) как студию программирования использовать нечего.
А за одно попробуем уйти от интерфейса командной строки и Blender’a – будет еще один повод поговорить о независимости Blender’а. Вы думаете невозможно? Возможно все, главное хотеть.



Как Вам интерфейс для нашей программки-переворотчика чисел? Симпатичный, правда?
Написан он с помощью библиотеки wx. Скачать эту библиотеку можно отсюда http://wxPython.org. Я использую вариант этой библиотеки для Windows, но на сайте можно найти варианты библиотеки и для других систем.
Часть кода можно увидеть не на скриншоте, но все же лучше продублирую код целиком:

import wx

'''
autor : ArkSmoke
url : http://arkpython.blogspot.com
date : 10.09
data : work with wx in Blender

'''


class MyWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, id = -1, parent = None, pos = wx.Point(0,0), size = wx.Size(250,150), title = 'My first Window with Blender')
self.panel = wx.Panel(self)
self.buttonResult = wx.Button(id=-1, label='Work',name='button_work', parent=self.panel, pos=wx.Point(100, 70), size=wx.Size(50, 23), style=0)

self.textCtrlInfo = wx.TextCtrl(id=-1, name='textCtrl_info', parent=self.panel, pos=wx.Point(8, 8), size=wx.Size(232, 21), style=0, value='1234567')
self.Bind(wx.EVT_BUTTON, self.OnOperationClick, self.buttonResult)

def OnOperationClick(self,event):
try:
number = int(self.textCtrlInfo.GetValue())
except (TypeError, ValueError):
print('error')
return
dt = number
td = 0
while dt > 0:
td = td * 10 +(dt % 10)
dt = dt // 10

self.textCtrlInfo.SetValue(str(td))

class CalcApp(wx.App):
def OnInit(self):
self.main = MyWindow()
self.main.Show()
self.SetTopWindow(self.main)
return True

def main():
application = CalcApp()
application.MainLoop()

main()

Ну как Вам – скрипт в 46 строк уже более или менее серьезная вещь. Но давайте посмотрим, как он работает. Главная функция в нем – main(). Вы же помните логику работы всех приложений с окнами?
Пока существует окно, отслеживаются и обрабатываются все события, связанные с этим окном. К слову сказать, закрытие окна тоже событие, которое, впрочем, может не останавливать работу программы, но об этом говорить мы не станем.
Цикл обработки событий в Delphi осуществляется следующим образом:

While GetMessage(Msg,0,0,0) do begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;


простите не сумел удержаться, что не вставить кусок из этого языка – часто еще думаю именно на Pascal’е. Но это цикл для работы с GUI, если же Вы используете интерфейс командной строки, то для этой цели можно использовать бесконечный цикл while. Оговорив условия выхода – например, команда Quit, или номер пункта меню, соответствующий выходу из цикла – простор воображения.
Но все это я рассказал для того, чтобы Вы вспомнили принцип работы программ – работать до тех пор, пока не получена команда прекратить работу. Отсутствие события – тоже событие, которое обрабатывается определенным образом, например, переход в программу скринсайвер. Логично? Логично. Едем дальше.
Нечто подобное происходит и в Python при использовании библиотеки wx – этим занимается MainLoop(), но, для начала, нужно указать с каким именно окном мы работаем. Первая строчка функции main()

application = CalcApp()

CalcApp() – это уже наш собственный класс, в котором мы создаем окно и все события, связанные с ним. Собственно говоря, у нас есть всего одно событие – нажатие на кнопку. А вот само окно и все объекты, находящиеся на окне создавать придется соответствующими функциями: wx.Button – для кнопки и wx.TextCtrl – для текстового поля.
В классе CalcApp() основой является окно - MyWindow(). Тоже самодельный класс, именно в нем и описано все, что касается окна.

class CalcApp(wx.App):
def OnInit(self):
self.main = MyWindow()
self.main.Show()
self.SetTopWindow(self.main)
return True


Остальное нужно отображения нашего окошка, чтобы оно было видимым или нет. Вы только вдумайтесь невидимые окна! Но о хулиганстве писать не буду.
Переходим к классу MyWindow(). Он состоит из описания главного окна и всех компонентов, которые располагаются на главном окне.

wx.Frame.__init__(self, id = -1, parent = None, pos = wx.Point(0,0), size = wx.Size(250,150), title = 'My first Window with Blender')
self.panel = wx.Panel(self)
self.buttonResult = wx.Button(id=-1, label='Work',name='button_work', parent=self.panel, pos=wx.Point(100, 70), size=wx.Size(50, 23), style=0)

self.textCtrlInfo = wx.TextCtrl(id=-1, name='textCtrl_info', parent=self.panel, pos=wx.Point(8, 8), size=wx.Size(232, 21), style=0, value='1234567')

Самое главное в этом классе – связь между событием – нажатием кнопки и самой этой кнопки.

self.Bind(wx.EVT_BUTTON, self.OnOperationClick, self.buttonResult)

Функция Bind() осуществляет эту связь. Первый параметр показывает от какого объекта приходит событие, второй параметр – какое именно событие, тритий – уточнят имя побеспокоенного объекта.
Соответственно реакция объекта располагается во втором параметре.

def OnOperationClick(self,event):
try:
number = int(self.textCtrlInfo.GetValue())
except (TypeError, ValueError):
print('error')
return
dt = number
td = 0
while dt > 0:
td = td * 10 +(dt % 10)
dt = dt // 10

self.textCtrlInfo.SetValue(str(td))

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

Вот вроде бы и все. Blender может прекрасно работать и с библиотеками, которые не входят в поставку как самого Blender’a, так и самого Python. Хотя, может быть, с библиотекой wx работать удобнее, используя некие студии, позволяющие делать интерфейсы будущих программ визуально, но любая такая студия, берущая на себя рутинную работу, добавляет свой код, который может увеличить, как объем скрипта, так и сказаться на скорости его работы. В общем, приобретая что-то, что-то обязательно теряешь. Всегда все можно прописать руками, тогда уже знаешь каждую строчку и ориентироваться легче, хотя на первый взгляд это кажется и дольше сложнее. Но, где сложнее, там достойнее.

3 комментария:

  1. Аркадий... Вы выдаёте свинью за лошадь. Прочитал эту вашу статью и ту, про "магическое квадратное становится круглым". При чём тут блендер? Ни при чём.
    А описывать свои тыканья в изучении питона - не совсем хорошо. Хватит писать тупые статьи на тему "а вы не знали?! А ручки-то вот они!". Если уж рассматриваете питон в свете блендера, то полезнее было бы захреначить скрипт, генерирующий ... ... молнии. Или генератор окон, стульев, деревьев, анимацию толпы и т.д.

    ОтветитьУдалить
  2. Всему свой срок -- дойдем и до молний и людей (эти скрипты уже готовые видеть мне доводилось), а то что "А описывать свои тыканья в изучении питона - не совсем хорошо" полностью согласен, только это не "тыканья в изучении", а проверка работы Blender в стрессовой для него ситуации. К слову, эта проверка выявила кое-какие баги, которые, в прочем, на работу системы никак не сказываются (не считая вылета программы)

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

    Пожелание учел. Спасибо за комментарий. Сел писать скрит молнии.

    Рад любой любой обратной связи

    ОтветитьУдалить
  3. Давай, это будет полезнее. Удачи :-)

    ОтветитьУдалить