I am having a hard time restoring a window after it has been minimized.
Minimize works fine, but i am trying to open the window back up.. self restores but Vodka_Frame doesn't.
Here is my code:
def minimizeProgram(event):
self.Iconize()
Vodka_Frame.Iconize()
def maximizeProgram(event):
if self.IsIconized()=='True' or Vodka_Frame.IsIconized()=='True':
self.Iconize(False)
Vodka_Frame.Iconize(False)
self.Show(True)
Vodka_Frame.Show(True)
self.Raise()
Vodka_Frame.Raise()
#### Catch the minimize event and minimize both windows.
self.Bind(wx.EVT_ICONIZE,minimizeProgram)
#### Catch the maximize event and maximize both windows.
self.Bind(wx.EVT_LEFT_DCLICK,maximizeProgram)
What am i doing wrong? How can i get my windows back! :)
I'm not sure what you're doing wrong without a small runnable example. However, I created the following simple script that works for me:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, parent=None, title="Test")
panel = MyPanel(self)
self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.toggleIconize, self.timer)
self.timer.Start(5000)
self.Show()
#----------------------------------------------------------------------
def toggleIconize(self, event):
""""""
if self.IsIconized() == True:
print "raising..."
self.Iconize(False)
self.Raise()
else:
print "minimizing!"
self.Iconize()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Basically it just minimizes and raises itself every 5 seconds. I am using Python 2.6.6 and wxPython 2.8.12.1 on Windows 7 Pro.
The relationship between your frames is not clear, but if you make the other frame child of the main one (i.e. specify the main frame as its parent when creating it), then it will be minimized and restored automatically when the main frame is minimized or restored, without you having to do anything special.
Related
I am a newbie in wx.python and python and wanted to use the MultiSplitterWindow.py demo code in my own application.
I have read other stackoverflow entries regarding this subject but the answers given there don't seem to work for me.
I would really appreciate if anybody could help me to solve this issue.
As the demos use the demo framework:
if __name__ == '__main__':
import sys,os
import run
run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])
It does not work in my app, I have tried replacing the above using the example given in:
[] http://wiki.wxpython.org/Using%20wxPython%20Demo%20Code
But I might be doing something wrong because I does not work.
Any help is much appreciated.
I wrote about this on the wxPython wiki:
http://wiki.wxpython.org/Using%20wxPython%20Demo%20Code
Most of the time, you can copy the relevant portions of the widget code in question and paste it in your own code. The part you don't want is the references to self.log. That just allows the demo to log the messages and is demo specific code. I would actually rewrite my initial example to look like the following though:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
########################################################################
class MyFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Demo Test")
panel = MyPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Now if you want to copy the code in from the demo, you won't have to change all the self instances to `self.panel':
import wx
from wx.lib.wordwrap import wordwrap
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
b = wx.Button(self, -1, "Show a wx.AboutBox", (50,50))
self.Bind(wx.EVT_BUTTON, self.OnButton, b)
def OnButton(self, evt):
# First we create and fill the info object
info = wx.AboutDialogInfo()
info.Name = "Hello World"
info.Version = "1.2.3"
info.Copyright = "(C) 2006 Programmers and Coders Everywhere"
info.Description = wordwrap(
"A \"hello world\" program is a software program that prints out "
"\"Hello world!\" on a display device. It is used in many introductory "
"tutorials for teaching a programming language."
"\n\nSuch a program is typically one of the simplest programs possible "
"in a computer language. A \"hello world\" program can be a useful "
"sanity test to make sure that a language's compiler, development "
"environment, and run-time environment are correctly installed.",
350, wx.ClientDC(self))
info.WebSite = ("http://en.wikipedia.org/wiki/Hello_world", "Hello World home page")
info.Developers = [ "Joe Programmer",
"Jane Coder",
"Vippy the Mascot" ]
info.License = wordwrap(licenseText, 500, wx.ClientDC(self))
# Then we call wx.AboutBox giving it that info object
wx.AboutBox(info)
########################################################################
class MyFrame(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, title="Demo Test")
panel = MyPanel(self)
self.Show()
licenseText = "blah " * 250 + "\n\n" +"yadda " * 100
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
Download demos from here http://wxpython.org/download.php install and go C:\Program Files\wxPython3.0-Docs-and-Demos\demo and run.
I have the following code and I'm on OSX. However, I'm expecting to see a toolbar icon but I'm not seeing one. Am I doing something wrong or should it work on Windows? Here's the code
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,size=(400, 350))
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
self.panel = wx.Panel(self)
toolbar = wx.ToolBar(self, size=(-1, 128))
toolbar.SetToolBitmapSize((128,128))
bmp2 = wx.ArtProvider.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_OTHER, (128,128))
toolbar.AddLabelTool(-1, label="Add", bitmap=bmp2,
shortHelp="Add", kind=wx.ITEM_NORMAL)
toolbar.Realize()
self.SetToolBar(toolbar)
if __name__ == '__main__':
app = wx.App()
Example(None, title='')
app.MainLoop()
Thanks
The call to Realize needs to happen after the SetToolBar. This is because there are two different kinds of toolbars on OSX and which is chosen depends on if it is attached to a frame or not, and all that happens in the Realize call. Also, OSX is picky about the size of the tools, and the 128 you use will likely be reduced to a supported size.
The following Python code runs fine on windows, but cause a segmentation fault on
osx. Any suggestions why? It does not make a difference to use CallAfter...
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(wx.StaticText(self, -1, 'Static text'))
self.sizer.Add(wx.Button(self, -1, 'Button'))
self.SetSizer(self.sizer)
self.Bind(wx.EVT_BUTTON, self.on_button)
def on_button(self, event):
self.sizer.Clear()
self.DestroyChildren()
app = wx.App()
frame = myFrame()
frame.Show()
app.MainLoop()
It is because there are still system messages pending for the destroyed widgets, (mouse motion in this case) as well as the possibility that the code that is run after the return from the event handler will try to use the destroyed widgets (calling methods or accessing attributes.)
Using CallAfter to delay the destruction does solve the problem for me, which version of wxPython are you using? If this doesn't work for you then you may want to try using wx.CallLater instead, with a small timeout value.
import wx
class myFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(wx.StaticText(self, -1, 'Static text'))
self.sizer.Add(wx.Button(self, -1, 'Button'))
self.SetSizer(self.sizer)
self.Bind(wx.EVT_BUTTON, self.on_button)
def on_button(self, event):
wx.CallAfter(self.doit)
def doit(self):
self.sizer.Clear()
self.DestroyChildren()
app = wx.App()
frame = myFrame()
frame.Show()
app.MainLoop()
I've boiled my problem down to the example code shown in this post. Note that I'm not calling app.MainLoop() because this isn't an interactive window; I want it to pop up at the beginning, show some progress bars while work happens, and disappear when complete.
My (limited) understanding of wxPython and wx.Yield() led me to believe that calling wx.Yield() after some UI work would flush those changes to the display. That is not occurring -- when I run this script, there is a gray box where "Hello World" should be.
What am I doing wrong?
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, size=(400,400))
self.panel = wx.Panel(self, -1)
wx.StaticText(self.panel, -1, "Hello World", (20,20))
wx.Yield()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, -1)
self.frame.Show(True)
self.SetTopWindow(self.frame)
return True
def run():
app = MyApp(redirect=False)
import time; time.sleep(5)
run()
You need to be yielding or updating on a regular basis, so that when your OS/window manager sends repaint messages to your app, it can handle them. I am not 100% sure about wxPython as I haven't used it recently but I don't think you can do what you want without the main loop to handle the messages appropriately.
You might find something useful here about threading the main loop, however (as well as explanation of why the main loop is important): http://wiki.wxpython.org/MainLoopAsThread
instead of wx.Yield()
just call self.Update()
Without the MainLoop no events will be fired and also .Refresh will not work.
I guess wxSplashscreen may be what you are looking for. Example: http://wiki.wxpython.org/SplashScreen
Not that it will do the original poster any good after all this time but wx.Yield() would have done the job. It just needs to be in the right place as does the self.Show()
The following outputs a progress bar which gets updated.
import wx
import time
class MyFrame(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, size=(290,200))
self.panel = wx.Panel(self, -1)
wx.StaticText(self.panel, -1, "Hello World", (20,20))
self.gauge = wx.Gauge(self.panel, -1, 50, pos=(20,50), size=(250, 20))
self.Show()
n = 0
while n < 50:
n = n+1
self.gauge.SetValue(n)
wx.Yield()
time.sleep(1)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, -1)
self.SetTopWindow(self.frame)
return True
def run():
app = MyApp()
run()
It seems that this is specific to windows, here is an example that reproduces the effect:
import wx
def makegrid(window):
grid = wx.GridSizer(24, 10, 1, 1)
window.SetSizer(grid)
for i in xrange(240):
cell = wx.Panel(window)
cell.SetBackgroundColour(wx.Color(i, i, i))
grid.Add(cell, flag=wx.EXPAND)
class TestFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
makegrid(self)
class TestDialog(wx.Dialog):
def __init__(self, parent):
wx.Dialog.__init__(self, parent)
makegrid(self)
class Test(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
btn1 = wx.Button(self, label="Show Frame")
btn2 = wx.Button(self, label="Show Dialog")
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
sizer.Add(btn1, flag=wx.EXPAND)
sizer.Add(btn2, flag=wx.EXPAND)
btn1.Bind(wx.EVT_BUTTON, self.OnShowFrame)
btn2.Bind(wx.EVT_BUTTON, self.OnShowDialog)
def OnShowFrame(self, event):
TestFrame(self).Show()
def OnShowDialog(self, event):
TestDialog(self).ShowModal()
app = wx.PySimpleApp()
app.TopWindow = Test()
app.TopWindow.Show()
app.MainLoop()
I have tried this on the following configurations:
Windows 7 with Python 2.5.4 and wxPython 2.8.10.1
Windows XP with Python 2.5.2 and wxPython 2.8.7.1
Windows XP with Python 2.6.0 and wxPython 2.8.9.1
Ubuntu 9.04 with Python 2.6.2 and wxPython 2.8.9.1
The wxDialog wasn't slow only on Ubuntu.
I got a reply on the wxPython-users mailing list, the problem can be fixed by calling Layout explicitly before the dialog is shown.
This is really weird...
My guess is that this is due to
Windows and wxWidgets not dealing very
well with overlapping siblings, and so
when the sizer is doing the initial
layout and moving all the panels from
(0,0) to where they need to be that
something about the dialog is causing
all of them to be refreshed and
repainted at each move. If you
instead do the initial layout before
the dialog is shown then it is just as
fast as the frame.
You can do this by adding a call to window.Layout() at the end of
makegrid.
-- Robin Dunn