Quoting from the wxPython manual pages:
wx.Window.Refresh(eraseBackground = true
, rect = NULL)
Causes this window, and all of its children recursively (except under wxGTK1 where this is not implemented), to be repainted. Note that repainting doesn’t happen immediately but only during the next event loop iteration, if you need to update the window immediately you should use Update instead.
^ See, calling Refresh() sort of puts your item in a queue of things to be repainted the next time any repainting gets done in general. But that won’t happen until one of several possible other things happen, the easiest example of which is a sizing event (either the user resizes the window or something else within the app triggers a similar condition).
So Refresh() does work, strictly speaking, but just not to immediately effect the color change in this case.
The docs also state that SendSizeEvent() is outdated if you’re using a layout that involves sizers, and that Layout() should get called on the same window instead.
One helpful way to see this chain of events is as follows: you asked the window to repaint itself and it did… it changed all the right bits in the memory representation of what it looks like, in order to represent the new color that should be seen. But nothing had yet told the operating system that that change had been made. For performance reasons, the OS doesn’t check every existing window continuously to see whether it needs to be redone on screen. It waits to be signalled. And wxPython does not send such a signal until it knows it needs to. Furthermore, also for performance reasons, wxPython itself is not continuously checking to see if any of your windows have changed and therefore need to be re-shown. It too waits until it gets an appropriate reason to believe something is different and needs to be updated. That signal can be various things, but the one that typically comes first and clearest in the learning process is a size event. A size event is part of what goes on in a Layout() event.
So the missing link is just that you have to send a final signal, after changing something about a window that you want the user to see immediately, so that wxPython (and then your operating system) can make the changes effective on-screen.
The beneficial flip side of this is that if you had a complex series of changes to make and you didn’t want the user to see a lot of messy reorganization (with possible visual “flickering”) taking place, the system is set up to allow you to do all that then send a size or layout event right at the end for a cleaner, one-time switchover to show the updated state of the window in question.
···
On 6/8/07, 7stud bbxx789_05ss@yahoo.com wrote:
The book says:
However, setting the panel background color doesn’t immediately change its
appearance. Instead, something needs to trigger an event that causes the
panel to repaint itself, using its new background color property. One way to
trigger such an event is to ask the panel to refresh itself:
app.frame.panel.Refresh()
So I typed in:
app.frame.panel.Refresh()
And nothing in the window turned blue.
Try calling app.frame.SendSizeEvent().
Ok. I closed out the pycrust and program windows, and I did another pywrap,
and this time instead of typing:
app.frame.panel.Refresh()
I typed in:
app.frame.SendSizeEvent()
and that caused the whole window to turn blue. Now my question is this: why
does “wxPython in Action” say to do a Refresh() instead of a SendSizeEvent()?
It’s not a painting problem, it is a sizing problem. You’re leaving
panel at the default (very small) size, and the frame’s auto size magic
only happens when the frame gets a size event.
I don’t know what that means or what “auto size magic” is. I did try using
SetMinSize() on the panel before making by original post because in my limited
experience when nothing is in a panel, it shrinks to 0.
But since the frame is
already shown it doesn’t get a size event at this point in time.
Right. So are you saying the only way to make a window redraw itself once
it’s displayed is with a size event(assuming it doesn’t get covered and
uncovered by another window)? In other words, Refresh() doesn’t and shouldn’t
work? Also, why is it that after the panel is repainted blue, I am able to
use SetBackgroundColour() to change the panel to the color red without having
to do a SendSizeEvent()?