I don't understand clearing a sizer to redraw it

I'm new to wx widgets, and I'm obviously missing something
fundamental. I'm trying to update a window with some ascii art. I
can make a window with the ascii art by just adding rows of StaticText
to a sizer. But I can't get rid of the test I've added to change the
window. If I Clear() the sizer then it has no more children, but
putting new text in overwrites the existing text.

Example program that doesn't work:

import wx

class wxGameApp(wx.App):
def updateMap( self, map ):
   font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL, False)
   frame = self.frame
   frame.mapSizer.Clear()
   for row in map:
     if isinstance( row, list ):
       row = ' '.join( row )
     text = wx.StaticText( frame, label=row )
     text.SetFont( font )
     frame.mapSizer.Add( text )
   self.frame.mapSizer.Layout()
   self.frame.SetSizer(frame.mapSizer)
   self.frame.mapSizer.Fit( self.frame )

   frame.Show()

def OnInit(self):
   frame = wx.Frame(None, title="Game")
   frame.mapSizer = wx.BoxSizer(wx.VERTICAL)
   self.frame = frame
   self.updateMap( ["This is a test"] )
   self.updateMap( ["No Map Loaded"] )
   frame.Show()
   self.SetTopWindow(frame)
   return True

app = wxGameApp( 0 )

app.MainLoop()

Your problem is that you are creating a new static text for each
line each time that you call update map, you need to create either
a multi-line static text or one for each line of your display area
Once preferably in an init class member that will be
called when your window is created. You can then clear and set
the text in the static text(s) in your OnUpdate method.

Gadget/Steve
···

On 05/04/2011 3:07 AM, Schlake wrote:


I'm new to wx widgets, and I'm obviously missing something
fundamental. I'm trying to update a window with some ascii art. I
can make a window with the ascii art by just adding rows of StaticText
to a sizer. But I can't get rid of the test I've added to change the
window. If I Clear() the sizer then it has no more children, but
putting new text in overwrites the existing text.
Example program that doesn't work:
import wx
class wxGameApp(wx.App):
def updateMap( self, map ):
font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL, False)
frame = self.frame
frame.mapSizer.Clear()
for row in map:
if isinstance( row, list ):
row = ' '.join( row )
text = wx.StaticText( frame, label=row )
text.SetFont( font )
frame.mapSizer.Add( text )
self.frame.mapSizer.Layout()
self.frame.SetSizer(frame.mapSizer)
self.frame.mapSizer.Fit( self.frame )
frame.Show()
def OnInit(self):
frame = wx.Frame(None, title="Game")
frame.mapSizer = wx.BoxSizer(wx.VERTICAL)
self.frame = frame
self.updateMap( ["This is a test"] )
self.updateMap( ["No Map Loaded"] )
frame.Show()
self.SetTopWindow(frame)
return True
app = wxGameApp( 0 )
app.MainLoop()

This doesn't make any sense. Is it not possible to remove the old
widgets before creating new ones? How do you ever redraw anything in
wx widgets if you can't get rid of old information?

···

On Tue, Apr 5, 2011 at 2:51 AM, Gadget/Steve <GadgetSteve@live.co.uk> wrote:

On 05/04/2011 3:07 AM, Schlake wrote:

Your problem is that you are creating a new static text for each line each
time that you call update map, you need to create either a multi-line static
text or one for each line of your display area Once preferably in an
__init__ class member that will be called when your window is created. You
can then clear and set the text in the static text(s) in your OnUpdate
method.

--
-- Schlake

And, even more confusing to me is that your idea worked. Despite the
fact that I had called Clear() on the sizer and the text widget had
been removed from the sizer. What is going on here? What am I
missing? Does Clear() not actually remove items? If I call
GetChildren() after a Clear() is certainly looks like they have been
removed...

···

On Tue, Apr 5, 2011 at 6:50 AM, William D. Colburn (Schlake) <schlake@gmail.com> wrote:

On Tue, Apr 5, 2011 at 2:51 AM, Gadget/Steve <GadgetSteve@live.co.uk> wrote:

On 05/04/2011 3:07 AM, Schlake wrote:

This doesn't make any sense. Is it not possible to remove the old
widgets before creating new ones? How do you ever redraw anything in
wx widgets if you can't get rid of old information?

--
-- Schlake

When you used sizer.Clear() you didn’t pass the flag that says to also
delete the child windows. From the docs:
Detaches all children from the sizer. If delete_windows is true then child windows will also be deleted.

Detaching just means it is no longer sized by that sizer, but it still exists.
So what if you try your original code with:

frame.mapSizer.Clear(delete_windows=True)

···

On Tue, Apr 5, 2011 at 9:08 AM, William D. Colburn (Schlake) schlake@gmail.com wrote:

On Tue, Apr 5, 2011 at 6:50 AM, William D. Colburn (Schlake) > > schlake@gmail.com wrote:

On Tue, Apr 5, 2011 at 2:51 AM, Gadget/Steve GadgetSteve@live.co.uk wrote:

On 05/04/2011 3:07 AM, Schlake wrote:

This doesn’t make any sense. Is it not possible to remove the old

widgets before creating new ones? How do you ever redraw anything in

wx widgets if you can’t get rid of old information?

And, even more confusing to me is that your idea worked. Despite the

fact that I had called Clear() on the sizer and the text widget had

been removed from the sizer. What is going on here? What am I

missing? Does Clear() not actually remove items? If I call

GetChildren() after a Clear() is certainly looks like they have been

removed…

HEY! That's it! Something fundamental and simple that I was totally
missing! Thanks! This will go a long way towards not going crazy
when I toss in the buttons which also need to be destroyed and
recreated every click.

···

On Tue, Apr 5, 2011 at 8:17 AM, C M <cmpython@gmail.com> wrote:

When you used sizer.Clear() you didn't pass the flag that says to also
delete the child windows. From the docs:

--
-- Schlake

A sizer just looks like a container the items that are 'added' to it get
arranged by its rules when they are displayed, the static texts are not
strings but are windows displaying a string that the user can not
change, so the call to wx.StaticTex(TheText) creates a window to hold
and display TheText. When you add the static text object, (window), to
the sizer that sizer takes over responsibility for positioning it.
Clearing the sizer does not delete the contents just stops it being
responsible for the layout.

Hope that helps clarify things a little.

Gadget/Steve

···

On Tue, Apr 5, 2011 at 6:50 AM, William D. Colburn (Schlake) > <schlake@gmail.com> wrote:

On Tue, Apr 5, 2011 at 2:51 AM, Gadget/Steve <GadgetSteve@live.co.uk> wrote:

On 05/04/2011 3:07 AM, Schlake wrote:

This doesn't make any sense. Is it not possible to remove the old
widgets before creating new ones? How do you ever redraw anything in
wx widgets if you can't get rid of old information?

And, even more confusing to me is that your idea worked. Despite the
fact that I had called Clear() on the sizer and the text widget had
been removed from the sizer. What is going on here? What am I
missing? Does Clear() not actually remove items? If I call
GetChildren() after a Clear() is certainly looks like they have been
removed...

when I toss in the buttons which also need to be destroyed and

recreated every click.

Keep in mind you can also use .SetLabel(your_label_text) on a button or a StaticText to simply change what is written on it, rather than deleting and recreating them each time.

I'm hoping to avoid that as it adds a tremendous amount of
bookkeeping, and the UI isn't something I want to spend time on so the
faster I make it do anything the faster it can languish. Some unknown
number of buttons will appear and disappear each click, and they could
have the same name but do different things. I'm certainly hoping that
I can attach the same callback to each button and look it up by index
into the list I used to create the buttons to find out which button it
really is that was clicked, but I haven't dug that far into making
buttons in wx yet. I'm at work now, doing things that make me money,
so I can't play with this until I get off work. Buttons are on my
list to try and implement tonight. My real hope is that if someone
out there on the internet decides that this thing is cool that they
will write a working UI for it so I don't have too. So, if any of you
want to do stuff for free, I'm available to provide stuff for you to
do! :slight_smile:

Anyway, you've (by which I mean the people on the list and not just
CM) been immensely helpful today. Someone earlier explained what a
sizer was, and my notion of it was completely wrong. That helped a
lot. Pointing out that I was clearing the sizer wrong also helped a
lot.

···

On Tue, Apr 5, 2011 at 10:25 AM, C M <cmpython@gmail.com> wrote:

Keep in mind you can also use .SetLabel(your_label_text) on a button or a
StaticText to simply change what is written on it, rather than deleting and
recreating them each time.

--
-- Schlake

William D. Colburn (Schlake) wrote:

Keep in mind you can also use .SetLabel(your_label_text) on a button or a
StaticText to simply change what is written on it, rather than deleting and
recreating them each time.

I'm hoping to avoid that as it adds a tremendous amount of
bookkeeping, and the UI isn't something I want to spend time on so the
faster I make it do anything the faster it can languish. Some unknown
number of buttons will appear and disappear each click, and they could
have the same name but do different things.

This is just not the way things are done in UI applications. It's a
sweeping overgeneralization, of course, but widgets should not be coming
and going. There are two problem with it. First, it's a lot of
overhead for the system to create and destroy all of those structures.
Creating and destroying a window requires a kernel mode transition in
Windows. Updating an existing window can all be done in user mode. It
would be better to create a set of controls and manage their content
dynamically.

The second issue is one of usability. Users do not expect controls to
come and go. Now, if you're doing a "wizard" type app, where there are
several notebook pages that each contain different sets of controls,
users are familiar with that, but those are implemented by creating the
notebook pages pre-populated, and then showing or hiding the appropriate
sets as required.

I, of course, don't know what you are building, so I can't be specific.
I'm just trying to point out that it's hard to get a user interface
right. We've learned an awful lot about what works and what doesn't in
the 25 years since Windows and the Mac first appeared, and you ignore
"best practices" at your own risk.

Buttons are on my
list to try and implement tonight. My real hope is that if someone
out there on the internet decides that this thing is cool that they
will write a working UI for it so I don't have too.

You haven't said anything about what "this thing" is.

···

On Tue, Apr 5, 2011 at 10:25 AM, C M <cmpython@gmail.com> wrote:

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

What I'm building is a three dimensional rogue-esque game based on
playing ADVEN, ASYLUM (computers didn't have lower-case letters back
then), Rogue/LARN/Omega/MOIRA/Angband/HACK/Nethack and World of
Warcraft. The UI is mostly an annoyance to me, but an annoyance I
can't do without. I have an HTML based UI (source at
https://infohost.nmt.edu/~schlake/games/x31/index.txt and playable at
https://infohost.nmt.edu/~schlake/games/x31/index.cgi) but the back
end and processing has gotten large enough to make the web version
pretty much unplayable. If I had a GUI front end I wouldn't need to
reload the back end for every click, nor send the entire game state
across the network (yes, I could store it on the backend in a mysql
database, and earlier versions did that, but it turned out to be very
problematic for design purposes). There are a handful of buttons that
are static (the eleven cardinal directions), but most buttons come and
go based on the state of the game. If you are adjacent to a
characterClass object, then a "hello" button appears along with
whatever other actions that npc has available (currently my game only
has a money changer (because hookers only take exact change) and some
hookers (1 in 7 chance they rob you and dump you in the sewers). If
you are adjacent to a doorClass fill then you might get one or two a
variety of buttons (lock, unlock, open, close) depending on the state
of the door. Currently the map is just a flat omnipotent scan in x
and y around the player, with an adjustable z offset to look up and
down. Eventually I hope to pass back a smarter map with line of sight
and tooltips for items, and even more eventually, I want to provide a
first person view like ASYLUM did back on my TRS-80. But in the
meantime all I need is something to test the back end with. If you
look, you will notice that the buttons are created off interactions
with hints. The hints will eventually be used to group things
together, such as inventory interactions, combat interactions, etc.
Right now it only knows what movement interactions are, and it puts
those into a fixed table of movement with unavailable moves greyed
out.

To summarize so far, at every move there will be some number of
buttons that need to appear which have very little grouping and, aside
from movement, no fixed place in the GUI. The faster I can make a GUI
that lets me test the backend, the sooner I can work on my short term
goals of finding a way to implement NPC-movement, NPC-combat, adding
an inventory to the game, and expanding my map.

My GUI plan is to make a horizontal sizer that puts the map and
command-buttons (in a vertical sizer) next to a scrolling message
panel (that holds messages from objects and debugging information).
Attractiveness isn't an issue. I just need the buttons to appear when
a possible interaction is created.

Really, if I ever get this all sorted out (I'm on version 31 and I
started about 4 years ago) in Python I plan to rewrite it in C++ and
(probably) Qt. But I have pages and pages of concept ideas that are
far from being worked through, and I only do this in my spare time
when someone has just ninja-looted an item level 359 purple BoE drop
from a random instance and I'm too pissed off to play WoW.

Second summary: that was lots of things you probably didn't care about. :slight_smile:

···

On Tue, Apr 5, 2011 at 11:49 AM, Tim Roberts <timr@probo.com> wrote:

I, of course, don't know what you are building, so I can't be specific.
I'm just trying to point out that it's hard to get a user interface
right. We've learned an awful lot about what works and what doesn't in
the 25 years since Windows and the Mac first appeared, and you ignore
"best practices" at your own risk.

--
-- Schlake

William D. Colburn (Schlake) wrote:

What I'm building is a three dimensional rogue-esque game based on
playing ADVEN, ASYLUM (computers didn't have lower-case letters back
then), Rogue/LARN/Omega/MOIRA/Angband/HACK/Nethack and World of
Warcraft. .... There are a handful of buttons that
are static (the eleven cardinal directions), but most buttons come and
go based on the state of the game. If you are adjacent to a
characterClass object, then a "hello" button appears along with
whatever other actions that npc has available .... If
you are adjacent to a doorClass fill then you might get one or two a
variety of buttons (lock, unlock, open, close) depending on the state
of the door. Currently the map is just a flat omnipotent scan in x
and y around the player, with an adjustable z offset to look up and
down.
...
My GUI plan is to make a horizontal sizer that puts the map and
command-buttons (in a vertical sizer) next to a scrolling message
panel (that holds messages from objects and debugging information).
Attractiveness isn't an issue. I just need the buttons to appear when
a possible interaction is created.

At least you have a plan!

Games occupy a different strata in the programming world, where the
normal user interface rules do not always apply. I do think you would
find it easier to program if you created all possible buttons at the
beginning, hooked up their events, and then managed their visibility and
positioning on the fly, instead of making them come and go.

Second summary: that was lots of things you probably didn't care about. :slight_smile:

Well, I did ASK for it....

···

--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

The problem is that the UI should have no knowledge of the game other
than the bare minimum it needs. Every time I add something new to the
game it tickles me pink that I can just add anything I want to
listInteractions() and interact() and a working button magically
appears that does what it is meant to do without needing any UI work.

···

On Tue, Apr 5, 2011 at 12:30 PM, Tim Roberts <timr@probo.com> wrote:

Games occupy a different strata in the programming world, where the
normal user interface rules do not always apply. I do think you would
find it easier to program if you created all possible buttons at the
beginning, hooked up their events, and then managed their visibility and
positioning on the fly, instead of making them come and go.

--
-- Schlake

You might think about running the server and the browser on the same machine -- what I like to call a "Browser Interface Local Server" (BILS) app. That and some nifty AJAX-y things, and you should be able to get a pretty responsive app.

-Chris

···

On 4/5/11 11:18 AM, William D. Colburn (Schlake) wrote:

  I have an HTML based UI (source at
https://infohost.nmt.edu/~schlake/games/x31/index.txt and playable at
https://infohost.nmt.edu/~schlake/games/x31/index.cgi) but the back
end and processing has gotten large enough to make the web version
pretty much unplayable. If I had a GUI front end I wouldn't need to
reload the back end for every click, nor send the entire game state
across the network

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Well, it's our own little group in NOAA, but yes, we have one production BILS app, and we're thinking about doing more:

http://response.restoration.noaa.gov/cameochemicals

It's a web app, and the desktop version you can download is a BILS app (Pylons web server embedded in a wxPython app)

Here's my PyCon talk about it:

http://us.pycon.org/2009/conference/schedule/event/92/

I honestly haven't seen any other applications that do the full-on embedding, but a number of folks (like google, for instance) distribute apps that run a local server and the user uses their regular browser to interact with it.

There was a thread on this list about it a few months back -- I'm not sure what to search for to find it, though.

Also, you may want to look at WebGL -- it looks pretty darn cool, but not helpful if what you want are buttons and stuff. But there are a number of nifty JavaScript libs for those.

-Chris

···

On 4/5/11 12:46 PM, Malcolm Greene wrote:

Is NOAA building BILS based systems and if so are there any examples for
the public to look at?

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

Thank you Chris.

Regards,
Malcolm