wxPython - AnimationCtrl with Gif results in Kernel Crash - python

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()

Related

How to enable autoscrolling to bottom for wx.html.HtmlWindow

I am using wxPython and want my HtmlWindow to scroll down automatically after adding new content. I am using it as a log window inside my app. Unfortunately, I am struggling to get it working. Here is my sample with lacks the functionality:
import wx
import wx.html
class GUI(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.html = wx.html.HtmlWindow(self, -1, pos=(0, 0), size=(50, 50))
msg = '<pre>FOO</pre>'
for i in range(10):
self.html.AppendToPage(msg)
if __name__ == '__main__':
app = wx.App()
frame = GUI(parent=None)
frame.Show()
app.MainLoop()
I want the scrollbar showing the stack of "Foos" to be at the bottom instead of staying on top so that the latest logging content is shown to the user.
Arguably wx.html.HtmlWindow is the wrong tool to use.
You'd have to insert Anchors and then leap to each Anchor.
For a log, it's better to use a wx.TextCtrl e.g.
import wx
import time
class GUI(wx.Frame):
def __init__(self, parent):
super().__init__(parent)
self.log = wx.TextCtrl(self, wx.ID_ANY, size=(600, 480),
style=wx.TE_MULTILINE| wx.TE_READONLY| wx.VSCROLL)
# set initial position at the start
self.log.SetInsertionPoint(0)
self.Show()
msg = 'FOO\n'
for i in range(50):
self.log.write(msg)
wx.GetApp().Yield()
time.sleep(0.5)
if __name__ == '__main__':
app = wx.App()
frame = GUI(parent=None)
app.MainLoop()

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()

What is the correct way to link a button to open an other py file?

I have a big doubt because my script is not performing as it should be. So I have a simple main file with a button that opens a blank grid (codes below). The problem with this code is that it opens reportWindow the first time it executes, but if I close the report and I try to open it again I receive the error :
NameError: name 'TestFrame' is not defined
I've also removed if __name__ == '__main__' from the last lines of reportWindow.py because the script wasn't working with it. I tried if __name__ == 'main' as it's imported from main.py but it didn't work either.
Please, can someone show me how it should have been done the correct way?
Thank you
main.py
import wx
class Test(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id, "Frame aka Window", size=(300, 200))
panel = wx.Panel(self)
button = wx.Button(panel, label = "Exit", pos=(80, 80), size = (120,30))
self.Bind(wx.EVT_BUTTON, self.closebutton, button)
def closebutton(self,event):
from reportWindow import SimpleGrid
SimpleGrid(TestFrame, -1)
if __name__ == '__main__':
app = wx.App()
frame = Test(parent=None, id=1)
frame.Show()
app.MainLoop()
reportWindow.py
import wx
import wx.grid as gridlib
class SimpleGrid(gridlib.Grid): ##, mixins.GridAutoEditMixin):
def __init__(self, parent, log):
gridlib.Grid.__init__(self, parent, -1)
#[...Some code...]
class TestFrame(wx.Frame):
def __init__(self, parent, log):
wx.Frame.__init__(self, parent, 0, "Title", size=(1400,800))
self.grid = SimpleGrid(self, log)
#[...Some code...]
#if __name__ == '__main__':
import sys
from wx.lib.mixins.inspection import InspectableApp
app = InspectableApp(False)
frame = TestFrame(None, sys.stdout)
frame.Show(True)
#import wx.lib.inspection
#wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
Your code has a few of issues.
1) The NameError is occurring because you're not importing TestFrame from reportWindow.
2) Without if __name__ == "__main__" in reportWindow.py your program will create another wx.App and start another MainLoop which will block the first loop from receiving events etc... You should only create 1 App/MainLoop. It will also create the TestFrame the first time you import reportWindow.
3) It looks like you want SimpleGrid to be a child of TestFrame, but then you try to create it by itself in closebutton.
4) When creating the SimpleGrid you pass the TestFrame class instead of an instance of the TestFrame class.
Here is the modified code
# main.py
import wx, sys
class Test(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, "Frame aka Window", size=(300, 200))
panel = wx.Panel(self)
button = wx.Button(panel, label="Exit", pos=(80, 80), size=(120, 30))
self.Bind(wx.EVT_BUTTON, self.closebutton, button)
def closebutton(self, event):
from reportWindow import TestFrame
frame = TestFrame(self, sys.stdout)
frame.Show()
if __name__ == '__main__':
app = wx.App()
frame = Test(parent=None, id=1)
frame.Show()
app.MainLoop()
# reportWindow.py
import wx
import wx.grid as gridlib
class SimpleGrid(gridlib.Grid): ##, mixins.GridAutoEditMixin):
def __init__(self, parent, log):
gridlib.Grid.__init__(self, parent, -1)
# [...Some code...]
class TestFrame(wx.Frame):
def __init__(self, parent, log):
wx.Frame.__init__(self, parent, 0, "Title", size=(1400, 800))
self.grid = SimpleGrid(self, log)
# [...Some code...]
if __name__ == '__main__':
import sys
from wx.lib.mixins.inspection import InspectableApp
app = InspectableApp(False)
frame = TestFrame(None, sys.stdout)
frame.Show(True)
import wx.lib.inspection
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()

FigureCanvasWxAgg not resizing properly in panel (or notebook) in linux

I've written a program in wxpython that works just fine in windows but when tested in lunix I have some Display issues that that all occur in linux.
Here is a testapp that demonstrates the problem with the resizing of the FigureCanvasWxAgg in a panel, as seen the panel it self follows the resizingevent but the FigureCanvasWxAgg doesn't follow, this however is not a problem in Windows.
import wx
import matplotlib.figure as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx.lib.inspection
class Test(wx.Frame):
def __init__(self):
super(Test, self).__init__(parent=None, id=-1)
self.figure = plt.Figure()
self.panel = wx.Panel(self, 1)
self.figurepanel = FigureCanvas(self.panel, -1, self.figure)
self.axes1 = self.figure.add_subplot(111)
frame_box = wx.BoxSizer(wx.VERTICAL)
frame_box.AddStretchSpacer(prop=1)
frame_box.Add(self.panel, flag=wx.EXPAND, proportion=2)
frame_box.AddStretchSpacer(prop=1)
main_box = wx.BoxSizer(wx.HORIZONTAL)
main_box.AddStretchSpacer(prop=1)
main_box.Add(frame_box, flag=wx.EXPAND, proportion=1)
main_box.AddStretchSpacer(prop=1)
self.SetSizer(main_box)
self.Show()
self.Layout()
def main():
app = wx.App()
Test()
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
if __name__ == '__main__':
main()
What I would be very grateful to have answered is:
How do I resolve this issue of reszing FigureCanvasWxAgg in linux
Is there any difference in the general way of GUI programming with wxPython on Windows and in Linux
There are several issues with the code you posted:
You have horizontal and vertical spacer that expand as needed, which causes the central region to remain the same shape
self.figurepanel is not part of any sizer, which means it will not resize even if its container, self.panel does.
The code below produces a window filled by plot that resizes with the window:
import wx
import matplotlib.figure as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import wx.lib.inspection
class Test(wx.Frame):
def __init__(self):
super(Test, self).__init__(parent=None, id=-1)
self.panel = wx.Panel(self, 1)
self.panel.SetBackgroundColour('RED')
self.figure = plt.Figure()
self.axes1 = self.figure.add_subplot(111)
self.figurepanel = FigureCanvas(self.panel, -1, self.figure)
main_box = wx.BoxSizer(wx.HORIZONTAL)
main_box.Add(self.figurepanel, flag=wx.EXPAND, proportion=1)
self.panel.SetSizer(main_box)
frame_box = wx.BoxSizer(wx.VERTICAL)
frame_box.Add(self.panel, flag=wx.EXPAND, proportion=1)
self.SetSizer(frame_box)
self.Show()
self.Layout()
def main():
app = wx.App()
Test()
wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
if __name__ == '__main__':
main()
There is no need to do any manual resizing yourself, and there is no problem, I think, with resize event propagation. If there is there would be a lot more breakage than what you are seeing.
I think I fixed the problem. The problem is caused by the wx.EVT_SIZE witch seems to be automatic in Windows but not in Linux. So to fix the problem in Linux all you have to do is to bind the the wx.Panel to the wx.EVT_SIZE and then define an apropriate eventhandler that takes care of the resizing.
What did the trick for me was:
#code beneath is a part if the __init__ metod
self.panel = wx.Panel(self, -1)
self.figurepanel = FigureCanvas(self.panel, -1, self.figure)
self.panel.Bind(wx.EVT_SIZE, self.on_size)
....
#the eventhandler for the panel. The method resizes the the figurepanel and the figure.
def on_size(self, event):
pix = self.panel.GetClientSize()
self.figure.set_size_inches(pix[0]/self.figure.get_dpi(),
pix[1]/self.figure.get_dpi())
x,y = self.panel.GetSize()
self.figurepanel.SetSize((x-1, y-1))
self.figurepanel.SetSize((x, y))
self.figurepanel.draw()
event.Skip()

Animating gif in wxPython

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()

Categories

Resources