Animating gif in wxPython - python

I'm trying to animate a gif using wx-Python (2.7). The code listed below works but i want to create a function that animates the gif for me, so i can use it elsewhere. I've tried searching the internet but i can only find code that animates the gif within the __init__ function. Any ideas?
# -*- coding: cp1252 -*-
import wx
import wx.animate
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("black")
gif_fname = "skYmk.gif"
gif = wx.animate.GIFAnimationCtrl(self, id, gif_fname, pos=(10, 10))
gif.GetPlayer().UseBackgroundColour(True)
gif.Play()
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "wx.animate.GIFAnimationCtrl()", size = (200, 220))
MyPanel(frame, -1)
frame.Show(True)
app.MainLoop()

I don't understand your issue.... what is the problem in doing something like this?
import wx
import wx.animate
class MyPanel(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("black")
gif_fname = "skYmk.gif"
gif = wx.animate.GIFAnimationCtrl(self, id, gif_fname, pos=(10, 10))
gif.GetPlayer().UseBackgroundColour(True)
self.gif = gif
def CallMeLater(self, play=True):
if play:
self.gif.Play()
else:
self.gif.Stop()
app = wx.PySimpleApp()
frame = wx.Frame(None, -1, "wx.animate.GIFAnimationCtrl()", size = (200, 220))
MyPanel(frame, -1)
frame.Show(True)
app.MainLoop()

Related

Playing Animation with WxPython

I try to play a gif in my frame. I use this code in order to do it. Why doesn't it work?
(I use the last version of wxPython - 4.0.7.post2)
import wx
from wx.adv import AnimationCtrl
class Animate(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, -1, title)
self.animation = AnimationCtrl(self)
self.animation.LoadFile('scan.gif')
self.animation.Play()
self.Show()
app = wx.App()
frame = Animate(None, -1, 'Animation')
app.MainLoop()
The argument to the constructor wx.adv.Animation is the filename. So it has to be:
anim = wx.adv.Animation()
anim.LoadFile(r'C:\Users\yuval\PycharmProjects\MultiTyping\pictures\back_gif.gif')
or
anim = wx.adv.Animation(r'C:\Users\yuval\PycharmProjects\MultiTyping\pictures\back_gif.gif')
Furthermore, I recommend to add a wx.BoxSizer to the frame:
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(anim_ctrl)
frame.SetSizerAndFit(sizer)
See the example:
import wx
from wx.adv import AnimationCtrl, Animation
app=wx.App()
frame = wx.Frame(None, -1, title='2', pos=(0, 0), size=(200, 200))
app.SetTopWindow(frame)
anim = Animation(r'C:\Users\yuval\PycharmProjects\MultiTyping\pictures\back_gif.gif')
anim_ctrl = AnimationCtrl(frame, -1, anim)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(anim_ctrl)
frame.SetSizerAndFit(sizer)
frame.Show()
anim_ctrl.Play()
app.MainLoop()
I see nothing wrong with the answer given by #Rabbid76, I suggest that you run the code from the command line, rather than from within some ide.
Here is another take on your problem, it's as concise as I can make it and assumes a local file called scan.gif.
import wx
from wx.adv import AnimationCtrl
class Animate(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, -1, title)
self.animation = AnimationCtrl(self)
self.animation.LoadFile('scan.gif')
self.animation.Play()
self.Show()
app = wx.App()
frame = Animate(None, -1, 'Animation')
app.MainLoop()

wxPython - AnimationCtrl with Gif results in Kernel Crash

I use this piece of Code trying to display and animate a Gif inside my GUI. But if i run this, my Kernel dies instantly.
What did i do wrong?
Here is my Code:
import wx
from wx.adv import Animation, AnimationCtrl
class TestPanel(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1)
sizer = wx.BoxSizer(wx.VERTICAL)
gif_fname = wx.adv.Animation("Test.gif")
gif = wx.adv.AnimationCtrl(parent=self,anim=gif_fname)
gif.GetAnimation()
self.gif = gif
self.gif.Play()
sizer.Add(gif)
self.SetSizerAndFit(sizer)
self.Show()
if __name__ == '__main__':
test=wx.App()
TestPanel(None)
test.MainLoop()

Align ListBox in Frame wxpython

I'm trying to figure out how to align a ListBox properly. As soon as i insert the lines of ListBox, the layout transforms into a mess.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
oplist=[]
with open("options.txt","r") as f:
for line in f:
oplist.append(line.rstrip('\n'))
print(oplist)
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title = title, size=(200,300))
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
p = wx.Panel(self)
vbox= wx.BoxSizer(wx.VERTICAL)
self.l1 = wx.StaticText(p, label="Enter number", style=wx.ALIGN_CENTRE)
vbox.Add(self.l1, -1, wx.ALIGN_CENTER_HORIZONTAL, 200)
self.b1 = wx.Button(p, label="Buton 1")
vbox.Add(self.b1, -1, wx.ALIGN_CENTER_HORIZONTAL,100)
self.flistbox= wx.ListBox(self,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)
vbox.Add(self.flistbox, -1, wx.CENTER, 10)
p.SetSizer(vbox)
app = wx.App()
Example(None, title="BoxSizer")
app.MainLoop()
Here the outputs with and without:
The listbox is being parented to the frame by using self.
self.flistbox= wx.ListBox(
self,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)
It should be parented to the panel by using p like the other controls.
self.flistbox= wx.ListBox(
p,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)

Changing the image size dynamically when the sizer's size changes in wxPython

I am working with python v2.7 and wxPython v3.0 on Windows 8 OS.
In the code snippet provided below simply creates a frame which has a vertical sizer that contains an image and an other horizontal sizer that in turn contains two panels.
Question: When I resize the frame by dragging the border, the panels resize automatically. Unlike the panels the image doesn't resize? How can I make my image to behave like panels for the case of resizing?
Code: The image file used can be downloaded from here: green.bmp
import wx
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, style=wx.DEFAULT_FRAME_STYLE)
panelA = wx.Panel(self,-1)
imageFile = wx.Image('greenbig.bmp', wx.BITMAP_TYPE_ANY).ConvertToBitmap()
myBitmap = wx.StaticBitmap(panelA, -1, imageFile)
panel1 = wx.Panel(self, -1,style=wx.SIMPLE_BORDER)
panel2 = wx.Panel(self, -1, style=wx.SIMPLE_BORDER)
panelSizer = wx.BoxSizer(wx.HORIZONTAL)
panelSizer.Add(panel1, 1, wx.ALL|wx.EXPAND, 0)
panelSizer.Add(panel2, 1, wx.ALL|wx.EXPAND, 0)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(panelA, 1, wx.ALL|wx.EXPAND, 0)
sizer.Add(panelSizer, 1, wx.ALL|wx.EXPAND, 0)
self.SetSizer(sizer)
self.Show(True)
app = wx.App()
frame = Frame(None, wx.ID_ANY, 'Image')
app.MainLoop()
Thank you for your time!
(eight years later) I was struggling to show an image that was dynamically resized with the window frame. These days, I'm using Python 3 with wxPython version 4. I pieced this solution from a lot of reading of the documentation and tips on how best to use sizers. I then whittled my code down to the absolute minimum required to accomplish this narrow use case.
Notice that I don't ever call Frame.Layout() or Panel.Layout() because I rely on the initial size of the Frame and the fact that a single Panel in a Frame will be automatically resized with the Frame. Also, any call to Fit() was unnecessary. The sizer containing the ImagePanel does need the EXPAND flag, but the ImagePanel does not need a sizer itself.
Note: you'll have to supply your own example image to load.
import wx
class ImagePanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.img = wx.Image(width=1, height=1)
self.ctrl = wx.StaticBitmap(self, bitmap=self.img.ConvertToBitmap())
self.Bind(wx.EVT_SIZE, self.on_resize)
def load_image(self):
with open('image.png', 'rb') as fin:
self.img = wx.Image(fin)
self.update_bitmap()
def update_bitmap(self):
w, h = self.GetSize()
self.ctrl.SetBitmap(self.img.Scale(w, h).ConvertToBitmap())
def on_resize(self, evt):
self.update_bitmap()
class MainWindow(wx.Frame):
def __init__(self):
initial_size = wx.Size(width=480, height=480)
super().__init__(None, wx.ID_ANY, title='Main Window Title', size=initial_size)
self.panel = wx.Panel(self)
self.image = ImagePanel(self.panel)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.image, proportion=1, flag=wx.EXPAND)
self.panel.SetSizer(vbox)
if __name__ == '__main__':
app = wx.App()
win = MainWindow()
win.Show()
win.image.load_image()
app.MainLoop()
The image will never be resized automatically. If you want this behaviour, you need to handle wxEVT_SIZE and do it yourself in its handler.

Panel classes and switching between them

With my code, I've now decided that I need multiple screens to go between where the buttons and background will change
I think the easiest way for me to do that would be by defining panel classes, then creating one frame but I don't know how to link all the panels together on the frame. I know which buttons and images I want on each panel but I don't know how you define the panels and link them through a button click
import os
import pygame
import wx
import os
import game
class MainPanel(wx.Panel):
def __init__(self,parent,id):
image_file='main_screen.jpg'#loading an image file from the folder
bmp=wx.Bitmap(image_file)
self.bitmap = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
PlayButton=wx.Bitmap('play.jpg', wx.BITMAP_TYPE_ANY)
self.PlayButton=wx.BitmapButton(self.bitmap, -1, PlayButton, pos=(190,300))
self.PlayButton.Bind=(wx.EVT_BUTTON, self.opengame)
RulesButton=wx.Bitmap('rules.jpg', wx.BITMAP_TYPE_ANY)
self.RulesButton=wx.BitmapButton(self.bitmap, -1, RulesButton, pos=(190,370))
self.RulesButton.Bind=(wx.EVT_BUTTON, self.openrules)
ControlsButton=wx.Bitmap('controls.jpg', wx.BITMAP_TYPE_ANY)
self.ControlsButton=wx.BitmapButton(self.bitmap, -1, ControlsButton, pos=(190,440))
#self.ControlsButton.Bind=(wx.EVT_BUTTON, self.closeMe)
ExitButton=wx.Bitmap('exit.jpg', wx.BITMAP_TYPE_ANY)
self.ExitButton=wx.BitmapButton(self.bitmap,-1,ExitButton,pos=(190,510))
self.ExitButton.Bind(wx.EVT_BUTTON, self.closeexit)
self.Bind(wx.EVT_CLOSE, self.closewindow)
class ControlPanel(wx.Panel):
def __init__(self,parent,id):
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
image_file='controls.jpg'#loading an image file from the folder
bmp=wx.Bitmap(image_file)
self.bitmap2 = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
BackButton=wx.Bitmap('back.jpg',wx.BITMAP_TYPE_ANY)
self.BackButton=wx.BitmapButton(self.bitmap2,-1,BackButton, pos=400,100)
self.BackButton.Bind=(wx.EVT_BUTTON, self.goback)
class RulesPanel(wx.Panel):
def __init__(self,parent,id):
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
image_file='rules.jpg'#loading an image file from the folder
bmp=wx.Bitmap(image_file)
self.bitmap3 = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
BackButton=wx.Bitmap('back.jpg',wx.BITMAP_TYPE_ANY)
self.BackButton=wx.BitmapButton(self.bitmap3,-1,BackButton, pos=400,100)
self.BackButton.Bind=(wx.EVT_BUTTON, self.goback)
class MainFrame(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Compsci Vs. Sheep: The Game',size=(640,640))
def openrules(self,event):
def opengame(self):
game.start()
def opencontrols(self,event):
?
def goback(self,event):
?
def closewindow(self,event):
self.Destroy()
pygame.mixer.quit()
def closeexit
if __name__=='__main__':
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=4096)
pygame.mixer.music.load("exorcist.ogg")
pygame.mixer.music.play(-1)#music playing in program
app=wx.PySimpleApp()
frame=menu(parent=None,id=-1)
frame.Show()#shows the screen
app.MainLoop()
This is my new code which still doesn't work
import os
import pygame
import wx
def switch_to(name):
print "Pseudo switch",name
class MainFrame(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Compsci Vs. Sheep: The Game',size=(640,640))
self.box = wx.BoxSizer()
self._panels = {}
self._panels['main'] = MainPanel(self, -1)
self._panels['rules'] = RulesPanel(self, -1)
self._panels['rules'].Hide()
self.box.Add(self._panels['main'],1,wx.EXPAND)
self.box.Add(self._panels['rules'],1,wx.EXPAND)
self.SetSizer(self.box)
def switch_panel(self, name):
print "Switching to",name
return
for key, panel in self._panels.iteritems():
if key != name:
panel.Hide()
else:
panel.Show(True)
self.Layout()
class MainPanel(wx.Panel):
def __init__(self,parent,id):
wx.Panel.__init__(self,parent,id=wx.ID_ANY)
image_file='main_screen.jpg'#loading an image file from the folder
bmp=wx.Bitmap(image_file)
self.bitmap = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
PlayButton=wx.Bitmap('play.jpg', wx.BITMAP_TYPE_ANY)
self.PlayButton=wx.BitmapButton(self,-1, PlayButton, (190,300), (244,60))
RulesButton=wx.Bitmap('rules.jpg', wx.BITMAP_TYPE_ANY)
self.RulesButton=wx.BitmapButton(self, -1, RulesButton, (190,300), (244,60))
self.RulesButton.Bind=(wx.EVT_BUTTON, parent.switch_panel)
class RulesPanel(wx.Panel):
def __init__(self,parent,id):
wx.Panel.__init__(self, parent, id=wx.ID_ANY)
image_file='rules.jpg'#loading an image file from the folder
bmp=wx.Bitmap(image_file)
self.bitmap = wx.StaticBitmap(self, wx.ID_ANY, bmp, (0, 0))
if __name__=='__main__':
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=4096)
pygame.mixer.music.load("exorcist.ogg")
pygame.mixer.music.play(-1)#music playing in program
app = wx.PySimpleApp()
frame = MainFrame(parent=None,id=-1)
frame.Show()#shows the screen
app.MainLoop()
You could just create all the panels in your frame constructor and place them in a dictionary. Then you could create a function called switch_panel that hides all the panels except the one you wish to show. Example:
def MyFrame(wx.Frame):
# Dict for storing the panels.
_panels = {}
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, 'Example')
# Create all the panels.
self._panels['main'] = MainPanel(self, -1)
self._panels['control'] = ControlPanel(self, -1)
self._panels['rules'] = RulesPanel(self, -1)
# Hide all the panels initially.
for key, panel in self._panels.iteritems():
panel.Hide()
# Show the main panel.
self.switch_panel('main')
def switch_panel(self, name):
"""Function for switching between the frame's panels."""
for key, panel in self._panels.iteritems():
if key != name:
panel.Hide()
else:
panel.Show(True)
Now any time you call switch_panel with "main", "control" or "rules", that panel will be shown and the others will be hidden.
How do I call switch_panel on a button click?
Bind an event handler to the button, e.g.
my_button = wx.Button(self, -1, 'Click me!')
my_button.bind(
wx.EVT_BUTTON,
lambda e: self.switch_panel('control')
)

Categories

Resources