Something like Refresh but not

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.

Ram.

And also a question about `Refresh` while I'm at it: If my `OnPaint`
calls something that calls `Refresh`, will it cause another `OnPaint`?

Ram.

···

On Apr 10, 9:03 am, cool-RR <ram.rac...@gmail.com> 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.

Ram.

Hi,

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.

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 08:03, cool-RR wrote:

Hi,

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.

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 08:07, cool-RR wrote:

Okay, will avoid, thanks.

Ram.

···

On Sat, Apr 10, 2010 at 12:30 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

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.

Andrea.

Sorry, I’ll clarify. What I’m trying to do is have some function that will check some variable to see if the widget needs to change its appearance (“Recalculate”). If so, it will raise a flag called recaluclate_flag, and it’ll call Refresh. Refresh will cause OnPaint to start, and OnPaint will check if the recaluclate_flag is up, if so it’ll recalculate. In any case it will redraw.

So I want to have a function that’ll check if the widget needs to be recalculated, and if so it raises the flag and calls refresh. But I don’t want to be calling this function directly. I want to “call” it the same way you “call” OnPaint when you do Refresh. So I could “call” it several times from several different places, and it’ll execute just once, the same way it works with OnPaint,

Ram.

···

On Sat, Apr 10, 2010 at 12:29 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

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.

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.

Hi,

Hi,

> 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.

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.

Sorry, I'll clarify. What I'm trying to do is have some function that will
check some variable to see if the widget needs to change its appearance
("Recalculate"). If so, it will raise a flag called `recaluclate_flag`, and
it'll call Refresh. Refresh will cause OnPaint to start, and OnPaint will
check if the `recaluclate_flag` is up, if so it'll recalculate. In any case
it will redraw.
So I want to have a function that'll check if the widget needs to be
recalculated, and if so it raises the flag and calls refresh. But I don't
want to be calling this function directly. I want to "call" it the same way
you "call" OnPaint when you do Refresh. So I could "call" it several times
from several different places, and it'll execute just once, the same way it
works with OnPaint,

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

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 11:36, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:29 PM, Andrea Gavana <andrea.gavana@gmail.com> > wrote:

On 10 April 2010 08:03, cool-RR wrote:

Hi,

Hi,

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.

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.

Sorry, I’ll clarify. What I’m trying to do is have some function that will

check some variable to see if the widget needs to change its appearance

(“Recalculate”). If so, it will raise a flag called recaluclate_flag, and

it’ll call Refresh. Refresh will cause OnPaint to start, and OnPaint will

check if the recaluclate_flag is up, if so it’ll recalculate. In any case

it will redraw.

So I want to have a function that’ll check if the widget needs to be

recalculated, and if so it raises the flag and calls refresh. But I don’t

want to be calling this function directly. I want to “call” it the same way

you “call” OnPaint when you do Refresh. So I could “call” it several times

from several different places, and it’ll execute just once, the same way it

works with OnPaint,

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. I tried having a custom event with an handler, then calling it 100 times and seeing if it’ll “collapse” all the events to one handling. It didn’t, it did 100 handlings.

But when I did 100 times Refresh, it did just 1 OnPaint. That’s the behavior I’m looking for.

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.

Ram.

···

On Sat, Apr 10, 2010 at 12:43 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

On 10 April 2010 11:36, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:29 PM, Andrea Gavana andrea.gavana@gmail.com > > > wrote:

On 10 April 2010 08:03, cool-RR wrote:

Hi,

Hi,

>
>
>>
>> Hi,
>>
>> > 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.
>>
>> 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.
>
> Sorry, I'll clarify. What I'm trying to do is have some function that
> will
> check some variable to see if the widget needs to change its appearance
> ("Recalculate"). If so, it will raise a flag called `recaluclate_flag`,
> and
> it'll call Refresh. Refresh will cause OnPaint to start, and OnPaint
> will
> check if the `recaluclate_flag` is up, if so it'll recalculate. In any
> case
> it will redraw.
> So I want to have a function that'll check if the widget needs to be
> recalculated, and if so it raises the flag and calls refresh. But I
> don't
> want to be calling this function directly. I want to "call" it the same
> way
> you "call" OnPaint when you do Refresh. So I could "call" it several
> times
> from several different places, and it'll execute just once, the same way
> it
> works with OnPaint,

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.

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

?

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 11:47, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:43 PM, Andrea Gavana <andrea.gavana@gmail.com> > wrote:

On 10 April 2010 11:36, cool-RR wrote:
> On Sat, Apr 10, 2010 at 12:29 PM, Andrea Gavana >> > <andrea.gavana@gmail.com> >> > wrote:
>> On 10 April 2010 08:03, cool-RR 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?

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

?

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.

Ram.

···

On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

>> 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).

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 12:01, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana <andrea.gavana@gmail.com> > wrote:

Hi,

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).

I see.

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).

Andrea.

I’ll give you more specific details. There’s a variable pseudoclock somewhere in my program, and there’s a widget ScratchWheel. When something changes pseudoclock, the ScratchWheel might need to redraw, and might not. So after every change to pseudoclock, I want to check if ScratchWheel needs to redraw. So I want to recalculate, but redraw only if the recalculation says we need to redraw.

So what do I do? If I just raise the recalculation flag and call Refresh, it’s possible that no redraw is needed and the ScratchWheel will just waste time refreshing. If I call recalculate directly after changing pseudoclock, and then have the recalculation function call Refresh if a redraw is needed, then this is a problem too, cause I could have many pseudoclock changes happening rapidly, and I don’t want to run the recalculate function for every one of them. When the pseudoclock changes, I want to call a function that is to the Recalculate function what Refresh is to the OnPaint function. i.e., a function that even if it’s called 100 times, the Recalculate function will execute only once.

Ram.

···

On Sat, Apr 10, 2010 at 6:55 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

On 10 April 2010 12:01, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana andrea.gavana@gmail.com > > > wrote:

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.

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.
The Doomed City: Removal Group: the nightmare <==

···

On 10 April 2010 18:11, cool-RR wrote:

On Sat, Apr 10, 2010 at 6:55 PM, Andrea Gavana <andrea.gavana@gmail.com> > wrote:

Hi,

On 10 April 2010 12:01, cool-RR wrote:
>
>
> On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana >> > <andrea.gavana@gmail.com> >> > wrote:
>
>> 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).

I see.

>> 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).

Andrea.

I'll give you more specific details. There's a variable `pseudoclock`
somewhere in my program, and there's a widget `ScratchWheel`. When something
changes `pseudoclock`, the `ScratchWheel` *might* need to redraw, and might
not. So after every change to `pseudoclock`, I want to check if
`ScratchWheel` needs to redraw. So I want to recalculate, but redraw only if
the recalculation says we need to redraw.
So what do I do? If I just raise the recalculation flag and call `Refresh`,
it's possible that no redraw is needed and the `ScratchWheel` will just
waste time refreshing. If I call recalculate directly after changing
`pseudoclock`, and then have the recalculation function call `Refresh` if a
redraw is needed, then this is a problem too, cause I could have many
`pseudoclock` changes happening rapidly, and I don't want to run the
recalculate function for every one of them. When the `pseudoclock` changes,
I want to call a function that is to the `Recalculate` function what
`Refresh` is to the `OnPaint` function. i.e., a function that even if it's
called 100 times, the `Recalculate` function will execute only once.

Interesting. So is it called after every loop?

I’ll start implementing.

Ram.

···

On Sat, Apr 10, 2010 at 7:31 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

On 10 April 2010 18:11, cool-RR wrote:

On Sat, Apr 10, 2010 at 6:55 PM, Andrea Gavana andrea.gavana@gmail.com > > > wrote:

Hi,

On 10 April 2010 12:01, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana > > >> > andrea.gavana@gmail.com > > >> > wrote:

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).

I see.

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).

Andrea.

I’ll give you more specific details. There’s a variable pseudoclock

somewhere in my program, and there’s a widget ScratchWheel. When something

changes pseudoclock, the ScratchWheel might need to redraw, and might

not. So after every change to pseudoclock, I want to check if

ScratchWheel needs to redraw. So I want to recalculate, but redraw only if

the recalculation says we need to redraw.

So what do I do? If I just raise the recalculation flag and call Refresh,

it’s possible that no redraw is needed and the ScratchWheel will just

waste time refreshing. If I call recalculate directly after changing

pseudoclock, and then have the recalculation function call Refresh if a

redraw is needed, then this is a problem too, cause I could have many

pseudoclock changes happening rapidly, and I don’t want to run the

recalculate function for every one of them. When the pseudoclock changes,

I want to call a function that is to the Recalculate function what

Refresh is to the OnPaint function. i.e., a function that even if it’s

called 100 times, the Recalculate function will execute only once.

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.

Andrea.

I tried it now. OnInternalIdle gets called infrequently. My app is frequently busy because it’s rendering the simulation. I have seen that only once in a while OnInternalIdle gets called, and the widget doesn’t get refreshed frequently enough.

I may just stick with Refresh if you there’s no good solution…

Ram.

···

On Sat, Apr 10, 2010 at 9:15 PM, cool-RR cool-rr@cool-rr.com wrote:

On Sat, Apr 10, 2010 at 7:31 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

On 10 April 2010 18:11, cool-RR wrote:

On Sat, Apr 10, 2010 at 6:55 PM, Andrea Gavana andrea.gavana@gmail.com > > > > > wrote:

Hi,

On 10 April 2010 12:01, cool-RR wrote:

On Sat, Apr 10, 2010 at 12:55 PM, Andrea Gavana > > > > >> > andrea.gavana@gmail.com > > > > >> > wrote:

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).

I see.

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).

Andrea.

I’ll give you more specific details. There’s a variable pseudoclock

somewhere in my program, and there’s a widget ScratchWheel. When something

changes pseudoclock, the ScratchWheel might need to redraw, and might

not. So after every change to pseudoclock, I want to check if

ScratchWheel needs to redraw. So I want to recalculate, but redraw only if

the recalculation says we need to redraw.

So what do I do? If I just raise the recalculation flag and call Refresh,

it’s possible that no redraw is needed and the ScratchWheel will just

waste time refreshing. If I call recalculate directly after changing

pseudoclock, and then have the recalculation function call Refresh if a

redraw is needed, then this is a problem too, cause I could have many

pseudoclock changes happening rapidly, and I don’t want to run the

recalculate function for every one of them. When the pseudoclock changes,

I want to call a function that is to the Recalculate function what

Refresh is to the OnPaint function. i.e., a function that even if it’s

called 100 times, the Recalculate function will execute only once.

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.

Andrea.

Interesting. So is it called after every loop?

I’ll start implementing.

Ram.

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.

···

On 4/10/10 10:31 AM, Andrea Gavana wrote:

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),

--
Robin Dunn
Software Craftsman

Assuming the app gets idle. And in my app I can’t assume it, because it’s doing animation.

P.S., I’m gonna be hiking now until about Wed., so I’ll look at any other suggestions when I return.

Thanks for your help,

Ram.

···

On Sat, Apr 10, 2010 at 9:52 PM, Robin Dunn robin@alldunn.com wrote:

On 4/10/10 10:31 AM, Andrea Gavana wrote:

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

Hey all, I’m back from hiking.

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.

Ram.

···

On Sat, Apr 10, 2010 at 10:03 PM, cool-RR cool-rr@cool-rr.com wrote:

On Sat, Apr 10, 2010 at 9:52 PM, Robin Dunn robin@alldunn.com wrote:

On 4/10/10 10:31 AM, Andrea Gavana wrote:

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

Assuming the app gets idle. And in my app I can’t assume it, because it’s doing animation.

P.S., I’m gonna be hiking now until about Wed., so I’ll look at any other suggestions when I return.

Thanks for your help,

Ram.

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

So this will get called for every event being processed? Won’t this slow everything up? Also, how do I hack this into something that gets called once after every iteration of the loop?

Ram.

···

On Fri, Apr 16, 2010 at 5:50 PM, Robin Dunn robin@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

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en

Is there any way to force a refresh? I mean, cause the on_paint to be called regardless of what the OS considers dirty?

Ram.

···

On Sat, Apr 10, 2010 at 12:43 PM, Andrea Gavana andrea.gavana@gmail.com wrote:

Hi,

(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).

To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com

or visit http://groups.google.com/group/wxPython-users?hl=en