Is there some way to do it without causing the window to paint? i.e.
Something that has this same feature, just not refreshing the window.
Ram.
Ram.
I honestly don't understand... why would you call Refresh() if you
don't want to re-paint the window? What are you trying to do?
Andrea.
"Imagination Is The Only Weapon In The War Against Reality."
http://xoomer.alice.it/infinity77/
==> Never *EVER* use RemovalGroup for your house removal. You'll
regret it forever.
http://thedoomedcity.blogspot.com/2010/03/removal-group-nightmare.html <==
On 10 April 2010 08:07, cool-RR wrote:
> And also a question about `Refresh` while I'm at it: If my `OnPaint`
> calls something that calls `Refresh`, will it cause another `OnPaint`?
Don't do that: anything in the OnPaint should not trigger another
refresh in the window, or you could end up in an infinite refreshing
loop that slowly eats up all your CPU.
Hi,
Don't do that: anything in the OnPaint should not trigger another
On 10 April 2010 08:07, cool-RR wrote:
> And also a question about `Refresh` while I'm at it: If my `OnPaint`
> calls something that calls `Refresh`, will it cause another `OnPaint`?
refresh in the window, or you could end up in an infinite refreshing
loop that slowly eats up all your CPU.
Andrea.
Hi,
I honestly don't understand... why would you call Refresh() if you
On 10 April 2010 08:03, cool-RR wrote:
> I noticed a nice feature of `Window.Refresh()`: I can call Refresh to
> some window from several different places, and all the "refresh
> requests" will get collapsed into one, and only one `OnPaint` will
> take place.
>
> Is there some way to do it without causing the window to paint? i.e.
> Something that has this same feature, just not refreshing the window.
don't want to re-paint the window? What are you trying to do?
Andrea.
Ah, OK, I got it. Uhm, not sure if you can do it easily
(Refresh/OnPaint rely on the wxWidgets event system and ultimately to
the platform, which will decide if and when the window is "damaged"
and requires a repainting). However, you could still do something like
this:
def OnPaint(self, event):
# Create wx.PaintDC or friends
if not self.needs_recalculation:
return
self.Recalculate()
# Re-draw things
However, you could still do something like
this:
def OnPaint(self, event):
# Create wx.PaintDC or friends
if not self.needs_recalculation:
return
self.Recalculate()
# Re-draw things
Andrea.
Yes, the platform: it's the OS which will decide if the window needs
refreshing or not: you can call Refresh() a million time, but if you
don't use Update() right before/after the Refresh() call, the OS will
not redraw your window unless it has been "damaged" or covered or
changed in size or whatever.
>>
>> However, you could still do something like
>> this:
>>
>> def OnPaint(self, event):
>>
>> # Create wx.PaintDC or friends
>>
>> if not self.needs_recalculation:
>> return
>>
>> self.Recalculate()
>>
>> # Re-draw things
>>
>>
>> Andrea.
>>
>
> If I do this, I think it will fail when the widget doesn't need to be
> recalculated, just redrawn.
Uhm, how about:
def OnPaint(self, event):
# Create wx.PaintDC or friends
if self.needs_recalculation:
self.Recalculate()
# Re-draw things
?
Yes, the platform: it's the OS which will decide if the window needs>> Ah, OK, I got it. Uhm, not sure if you can do it easily
>> (Refresh/OnPaint rely on the wxWidgets event system and ultimately to
>> the platform, which will decide if and when the window is "damaged"
>> and requires a repainting).
>
> I got the impression there's something more than just events here.
refreshing or not: you can call Refresh() a million time, but if you
don't use Update() right before/after the Refresh() call, the OS will
not redraw your window unless it has been "damaged" or covered or
changed in size or whatever.
>>Uhm, how about:
>> However, you could still do something like
>> this:
>>
>> def OnPaint(self, event):
>>
>> # Create wx.PaintDC or friends
>>
>> if not self.needs_recalculation:
>> return
>>
>> self.Recalculate()
>>
>> # Re-draw things
>>
>>
>> Andrea.
>>
>
> If I do this, I think it will fail when the widget doesn't need to be
> recalculated, just redrawn.
if self.needs_recalculation:
def OnPaint(self, event):
# Create wx.PaintDC or friends
self.Recalculate()
# Re-draw things
?
Andrea.
On 10 April 2010 12:01, cool-RR wrote:
>
>
> On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana <andrea...@gmail.com>
> wrote:
>>
>>
>>
>> >> Ah, OK, I got it. Uhm, not sure if you can do it easily
>> >> (Refresh/OnPaint rely on the wxWidgets event system and ultimately to
>> >> the platform, which will decide if and when the window is "damaged"
>> >> and requires a repainting).
>> >
>> > I got the impression there's something more than just events here.
>>
>> Yes, the platform: it's the OS which will decide if the window needs
>> refreshing or not: you can call Refresh() a million time, but if you
>> don't use Update() right before/after the Refresh() call, the OS will
>> not redraw your window unless it has been "damaged" or covered or
>> changed in size or whatever.
>
> What do you mean? Let's say I have some panel that's sitting still and not
> being interrupted/damaged/covered. It won't refresh. Then some code does
> `panel.Refresh()`. It will cause that panel to refresh, no?
Sorry, what I meant is: Refresh will raise a request for a window
refresh to wx and to the platform, but the refreshing will not happen
until the next event loop iteration:
"""
virtual void wxWindow::Refresh ( bool eraseBackground = true, const
wxRect * rect = NULL ) [virtual]
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
"""
Moreover, if you are using double-buffering or if the platform uses
double-buffering implicitly (like Mac and possibly Windows 7, don't
know about Linux), I doubt it will redraw your window anyway *unless*
something happened to the window (content changed, resized, damaged,
whatever).
>> Uhm, how about:
>>
>> def OnPaint(self, event):
>>
>> # Create wx.PaintDC or friends
>>
>> if self.needs_recalculation:
>> self.Recalculate()
>>
>> # Re-draw things
>>
>> ?
>>
>> Andrea.
>
> This is what I have now. The problem is not there, but in the code that
> raises the `needs_calculation` flag. I want to have a function that checks
> if we need calculation, and if so raise the flag and call refresh. But I
> want to be able to "call" this function the way Refresh "calls" OnPaint.
Sorry, I am still confused: how is different to do what you ask and to
do what I posted above? You simply call Refresh(), and if there is
need for a re-calculation, the OnPaint method will take care of this
too. I used this kind of strategy myself in some of the AGW widgets,
even outside the OnPaint handler (for example, in a wx.EVT_IDLE event
handler).
>> Uhm, how about:Sorry, I am still confused: how is different to do what you ask and to
>>
>> def OnPaint(self, event):
>>
>> # Create wx.PaintDC or friends
>>
>> if self.needs_recalculation:
>> self.Recalculate()
>>
>> # Re-draw things
>>
>> ?
>>
>> Andrea.
>
> This is what I have now. The problem is not there, but in the code that
> raises the `needs_calculation` flag. I want to have a function that checks
> if we need calculation, and if so raise the flag and call refresh. But I
> want to be able to "call" this function the way Refresh "calls" OnPaint.
do what I posted above? You simply call Refresh(), and if there is
need for a re-calculation, the OnPaint method will take care of this
too. I used this kind of strategy myself in some of the AGW widgets,
even outside the OnPaint handler (for example, in a wx.EVT_IDLE event
handler).
Andrea.
OK, I understand. It seems to very overly complex, but there might be
a solution. I am not sure it will fit your problem but it's worth a
try. If your ScratchWheel is an instance of wx.PyControl (or
wx.PyPanel, or wx.PyWindow or any other wx.PySomething), my suggestion
is to define a method called OnInternalIdle inside your class. This
method gets called by wxWidgets/wxPython when the control is sitting
idle, and I have used it myself for CustomTreeCtrl to check if the
widget needed recalculation of items' positions, or refreshing, or
scrollbars adjustments and so on:
def OnInternalIdle(self):
"""
This method is normally only used internally, but sometimes an
application
may need it to implement functionality that should not be disabled by an
application defining an `OnIdle` handler in a derived class.
This method may be used to do delayed painting, for example, and most
implementations call `wx.Window.UpdateWindowUI` in order to
send update events
to the window in idle time.
"""
# after all changes have been done to the tree control,
# we actually redraw the tree when everything is over
if not self._needs_recalculation and not self._needs_refresh:
return
if self._needs_recalculation:
self._needs_recalculation = False
self.Recalculate()
if self._needs_refresh:
self.Refresh()
self._needs_refresh = False
Basically, what you should do is to change your
self._needs_recalculation and self._needs_refresh flag any (and every)
time you wish (based on your pseudoclock variable), then at some point
in the wxPython event loop wxPython will call this OnInternalIdle
method and redraw/recalculate your widget at idle time. I couldn't
find any performance issue with CustomTreeCtrl using this method, it
is very reliable and it doesn't waste memory/cpu.
> OK, I understand. It seems to very overly complex, but there might be
> a solution. I am not sure it will fit your problem but it's worth a
> try. If your ScratchWheel is an instance of wx.PyControl (or
> wx.PyPanel, or wx.PyWindow or any other wx.PySomething),
And if it isn't then you can do the same approach with a EVT_IDLE
handler. This is a fairly common pattern: set a flag from where ever,
check the flag in an idle handler, if it is set do something and clear
the flag.
--
Robin Dunn
Software Craftsman
http://wxPython.org
On 4/16/10 4:23 AM, cool-RR wrote:
Is there a way to have some action run after every iteration of
wxPython's event loop? I think this would solve this problem, and would
be very helpful in some other problems.
I think the closest thing we have to that is to override FilterEvent in your derived wx.App class. As it's name implies it is intended to use for filtering events, so it is actually called before each event is processed, but it should give you what you want. Just be sure to return -1 so the events will be processed normally. You'll also need to call SetCallFilterEvent(True) to turn on calls to your FilterEvent method.--
Robin Dunn
Hi,
<snip>
(Refresh/OnPaint rely on the wxWidgets event system and ultimately to
the platform, which will decide if and when the window is "damaged"
and requires a repainting).
Try this:> Is there any way to force a refresh? I mean, cause the `on_paint` to be
> called regardless of what the OS considers dirty?
self.Refresh()
self.Update()
Andrea.
On 4/18/10 6:39 AM, cool-RR wrote:
On Fri, Apr 16, 2010 at 5:50 PM, Robin Dunn <ro...@alldunn.com<mailto:ro...@alldunn.com>> wrote:
On 4/16/10 4:23 AM, cool-RR wrote:
Is there a way to have some action run after every iteration of
wxPython's event loop? I think this would solve this problem,
and would
be very helpful in some other problems.
I think the closest thing we have to that is to override FilterEvent
in your derived wx.App class. As it's name implies it is intended
to use for filtering events, so it is actually called before each
event is processed, but it should give you what you want. Just be
sure to return -1 so the events will be processed normally. You'll
also need to call SetCallFilterEvent(True) to turn on calls to your
FilterEvent method.
--
Robin Dunn
So this will get called for every event being processed?
Yes.
Won't this slow
everything up?
Perhaps (that is why you have to call a method to explicitly turn it on) but probably about the same as implementing your own MainLoop would.
Also, how do I hack this into something that gets called
once after every iteration of the loop?
Derive a class from wx.App. Give it a FilterEvent method. Do whatever you need from there. Return -1.
--
Robin Dunn