Who invalidated my object?

I’ve got this fascinating problem.

Somewhere in my huge program, someone is calling Invalidate on an object that is about four layers of subclassing down. When the debugger breaks in the drawing method, it shows the Paint event in the call stack. But there is no indication of what code called Invalidate to trigger that Paint.

I tried creating a method called redraw and put invalidate in there, then changed every call to invalidate into one to redraw. Then put a breakpoint in redraw. It never got there.

So it appears the invalidate is coming from a superclass. Its terribly interesting to sleuth this, but surely there is a better way. I was thinking, maybe I could override Invalidate…but then…what do I call in my new Invalidate? Invalidate? Sounds like a endless loop to me.

In any case, I’m sure I will track it down, but I just thought I would toss it out there and see if anyone had some good coding tricks for dealing with this kind of event-triggering situation.

TIA

A number of window related functions will “Refresh” the views/controls, which in turn will fire your invalidate routine.

Resizing, overlapping controls being refreshed, theme changing, app going in and out of focus, maybe others.

IMHO you should expect it to be called whenever and whereever and code accordingly.

1 Like

DOH. The trick that worked was of course to change all invalidate calls in super classes into calls to redraw. Then implement redraw in the superclass as well. Then break on that.

Still open to any great suggestions. I find that in a lot of code, often events get triggered in unexpected ways, and this isn’t obvious from the way the program runs. It could redraw the screen twice in a row when only once was required, and its so fast, you don’t really notice it. But I believe this can cause some sluggishness.

A couple of things.

  1. Invalidate is coalesced, so you can call it 100 times in a method, but the view only gets one paint event.
  2. You should do whatever you can to keep the paint event as fast as possible, move as much logic out of the paint event. Having a slow paint event can make your application feel slow.
2 Likes

Yes good point. Being reminded of it made me realize that the debugger might have the draw method being called twice, but that is not necessarily what would happen if not running the debugger. Because the two invalidates might have occurred close enough in time that the second one was just overwriting the “dirty” bit.

Here’s an idea. Put a System.DebugLog call in the redraw call, indicating the source of the call (could be a string passed to the redraw method). Then when breaking in the resultant Paint event, the debug window should be showing who caused the invalidate.

Its a bit annoying to add a string argument, not sure if in introspection there is a way to get the required info.

  1. Invalidate is coalesced, so you can call it 100 times in a method, but the view only gets one paint event.

In another post, people are trying to tell me this is not the case in a 64bit app I have been testing.

It may be that they are referring to refresh which calls a paint there and then.

Nope. I’ve been very clear.

Okay, sorry. I don’t know what goes on Windows or Linux. Spend too much time in the Mac universe.

2 Likes