пятница, 11 ноября 2011 г.

wxPython: Gif-анимация и прозрачность

Кратко об анимации в wxPython

Дяденька делает анимацию на wxPython
В wxPython средства для работы с анимацией имеются в виде пакета wx.animate. Пакет довольно нехитрый - всего несколько классов, из которых чаще всего в работе используются 2:

  1. wx.animate.Animation - инкапсулирует параметры анимации, а также поддерживает загрузку анимации из файла. Поддерживает Gif и Ani форматы анимаций.
  2. wx.animate.GifAnimationCtrl - Контрол для отрисовки проигрывания Gif-анимации в графическом интерфейсе приложения.
Последний - очень соблазнительное средство, так как позволяет фактически в несколько строчек добавить в окно готовую анимацию:

...
ag_fname
= r"progress.gif"
ag = wx.animate.GIFAnimationCtrl(self, -1, ag_fname, pos=(0, 0), size=(64,64))
ag.GetPlayer().UseBackgroundColour(True)     
ag.Play()

Довольно неплохо. И даже больше ... прозрачность.

Прозрачность

Третья строчка вышеприведенного кода намекает нам, что анимация будет использовать вместо цвета, который в ней установлен прозрачным - фоновый цвет окна. Поговаривают, что на GTK оно так и есть, но я, к сожалению, не имел удовольствия в этом убедится, так как пишу софт, давший вдохновение на написания этой статьи, исключительно для ОС Windows.

Что ж, на Windows оно немножко не совсем так. В случае, если окно, на котором находится контрол имеет установленный цвет фона без дополнительных излишеств - все отлично. Проблемы начинаются тогда, когда на форме вручную через графический контекст рисуется картинка или, чего хуже, форма вообще не прямоугольная, а произвольного формата (к сожалению, так получилось, что мой случай).

В таком случае GifAnimationCtrl только вредит, поскольку на нашей красивой форме вырисовывается анимация с прямоугольным серым (ну, или каким там у вас будет) фоном.

Выход есть

Что же, отбрасываем контрол, берем голую анимацию (благо wx.animate.Animation имеет все средства для получения информации о кадрах, их количестве и "прозрачном" цвете) и рисуем на необходимом окне пользуясь DC (естественно, BufferedDC, чтобы избежать неприятных миганий) и таймером. Все, что нам нужно:
  • wx.Timer
  • wx.animate.Animation (.GetFrameCount(), .GetFrame(), ...)
  • wx.BufferedDC
Единственное, что здесь важно, - метод GetFrame(frame_number) возвращает не wx.Bitmap, который рисуюют, а wx.Image. Поэтому, чтобы получить картинку для рисования, нужно сделать Animation.GetFrame(number).ConvertToBitmap().

При этом, если исходный файл анимации имеет прозрачный цвет, картинке даже не надо делать SetMask(), маска будет создана исходя из кадра и цвета прозрачности. Код приводить не буду, в различных ситуациях он может быть разным, но смысл, думаю, понятен.

5 комментариев:

  1. "Пакет довольно нехитрый - всего парочка классов, из которых чаще всего в работе используются 2"

    Т.е. все классы пакета используются чаще всего? ;)

    ОтветитьУдалить
  2. Ну почему же, есть еще их предки, которые удобны для наследования, если вы, например какую-то хитрую анимацию свою сделать хотите, или какой-ниьбудь еще формат анимации реализовать свой.

    ОтветитьУдалить
  3. Я к тому, что "пара" и "2" равнозначны

    ОтветитьУдалить
  4. Ладно, привык думать, что парочка == несколько, так уж и быть, поправлю =)

    ОтветитьУдалить
  5. Seminole Hard Rock Hotel and Casino - MapyRO
    A free on-site sports betting app review 익산 출장안마 and 동해 출장샵 list of 32000 Seminole 과천 출장샵 Hard Rock 제주 출장안마 Hotel and Casino parking 원주 출장마사지 lots, street parking, and valet parking lots.

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