wxPython - problem dynamically adding widgets?

F

Fazan

I'm trying to create a wxPython-based application with a list of
arbitrary widgets (in this case, progress bars). I want my
application to dynamically add or delete widgets from the list based
on some user action. I first tried using a BoxSizer, and dynamically
instantiated the new widgets and added them to the sizer at the right
time in my application. This caused my app to hang every time. Only
widgets which I created before displaying the main frame were working,
but subsequent widget creation caused the hanging behavior.

I've also played around with ListCtrl (with the LC_REPORT style) and
Grid objects to achieve the desired result with no success. ListCtrls
allow text and images to be added; I had hoped to implement my own
progress bars (instead of using the Gauge class) by resizing images in
a list. But the support for images in ListCtrls seems quite limited;
the image can only exist at the far left side of the list and is
limited to some fixed size. In order to implement a progress bar I
would need more control over the placement and size of the image.
Although Grids support some additional controls such as Choice and
CheckBox, they don't even support images and using a Grid seems
awfully heavyweight.

The sizer approach seems pretty straightforward but I can't figure out
why the app always locks up. Anyone have ideas about how to solve
this? TIA
 
J

Josiah Carlson

Although Grids support some additional controls such as Choice and
CheckBox, they don't even support images and using a Grid seems
awfully heavyweight.

You should take a look at the wxPython demo. It includes an example
where a Grid contains images; something like a thousand of them if I
remember correctly.

And I have not found grids to be that terribly heavy.

- Josiah
 
J

Jaime Wyant

What platform are you using? Did you call window.layout() after
adding the sizer items? The code below adds a colored panel to
MainFrame's sizer every 2 seconds (err, approximately). BTW - there
is a wxPython mailing list that you may be interested in. Visit
http://www.wxpython.org and look for a mailing lists link.

# wxPython sample...
import wx

# Hey, i'm a patriot!
colors = [wx.RED, wx.WHITE, wx.BLUE]

# Create the "main frame"
class MyFrame( wx.Frame ):
def __init__( self ):
wx.Frame.__init__( self, None, -1, "Test" )
# Create the sizer here / fill it later.
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(self.sizer)
self.SetSize( wx.Size( 640, 480 ) )
self.Centre()

# Timer to be called once every 2 or so seconds.
self.Bind(wx.EVT_TIMER, self.its_been_2_secs)
self.num_panels = 0

tmr = wx.Timer(self)
tmr.Start(2000)

def its_been_2_secs(self, e):
if self.num_panels == 10:
return

# Create a colored panel to add to the sizer
pnl = wx.Panel(self)
pnl.SetBackgroundColour(colors[self.num_panels % 3])
self.sizer.Add(pnl, 1, wx.EXPAND)
self.Layout()

self.num_panels += 1

class MyApp( wx.App ):
def OnInit( self ):
self.frame = MyFrame()
self.frame.Show( True )
return True

def main():
# Create the application and start it off with the MainLoop method
app = MyApp(0)
app.MainLoop()

if __name__ == "__main__":
main()
 
P

Paul McNett

Fazan said:
The sizer approach seems pretty straightforward but I can't
figure out why the app always locks up. Anyone have ideas
about how to solve this? TIA

You should really post your question on the wxPython-users list,
which is at:

http://www.wxpython.org/maillist.php

And in order to solve your problem, you're really going to need
to show us some code: what have you tried?

As a hunch, I'm guessing that you are adding your windows to the
sizer but not to a real parent window. A sizer isn't a window,
it is just an object. A window, such as a grid or a textctrl or
a static bitmap, needs a parent, such as your top-level frame.
You need to add your window to the parent (frame), and then
separately add your window to the sizer.
 
F

Fazan

Using the sample code, I was indeed able to get this to work using a
sizer. It turns out that my problem was a threading issue; by
creating the widgets and adding to the sizer in different thread, the
hanging problem went away.

Thanks to everyone who helped out!
 
P

Peter L Hansen

Fazan said:
Using the sample code, I was indeed able to get this to work using a
sizer. It turns out that my problem was a threading issue; by
creating the widgets and adding to the sizer in different thread, the
hanging problem went away.

Sounds dangerous... I hope you were using wx.CallAfter() to
interact with the GUI elements. I believe you *must* to
avoid potential crashes. (See
http://www.wxpython.org/docs/api/wx-module.html#CallAfter)

-Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,223
Members
46,814
Latest member
SpicetreeDigital

Latest Threads

Top