View.invalidate vs view.refresh
-
I experienced that a tool I was making seemed slow to use. I profiled the methods I used when the viewport was updating and everything seemed to be running rather fast.
I had been been using
view.invalidate
exclusively because of backwards compatibility.After switching to
view.refresh
everything was working as smooth as I'd originally expect. Though this is a 7.1+ method.The API docs says:
@unknownuser said:
View.invalidate
The invalidate method is used to refresh the view.@unknownuser said:
View.refresh
The refresh method is used to immediately refresh the view.From this I can understand why
.refresh
produce the effect I wished for - as it ensured the viewport would refresh. I'm guessing that when I invalidated the drawing got deferred to a later point - but I don't quite understand what governs when it's drawn.
Is it some time delay forview.invalidate
where there has to be a certain amount of idleness before the viewport is actually refreshed?Since
view.refresh
force the view to be redrawn - could you risk the drawing operations taking too much resources and causing lag? Should one add some frame-limiting control to how often one useview.refresh
? -
I think that if you are in the middle of a start/commit block the view.invalidate will kick in once it's done, view.refresh will kick in immediately - useful to let the user see what's changed part way through... For example you want to ask the user if they want to reverse faces - you need to let them see the current faces - in v7 it's only possible by adding another commit/start into the code as the view then auto-regen's on the UI.messagebox; in >=~v8 the refresh regen's the view within the current stat/commit block so you haven't had to introduce an extra undo step...
I tend to usebegin view.refresh rescue view.invalidate end
to trap for <~v8.
-
@tig said:
I think that if you are in the middle of a start/commit block the view.invalidate will kick in once it's done,
Not from my observations. I had a start operation at onLButtonDown, and committed at up.
.invalidate
would refresh during that time. (The disable_ui argument is set to false.) -
Doesn't invalidate undo anything that's temporary from 'view.draw...' and then geometry outside of the start/commit, but refresh does both inside the start/commit block ?
-
Invalidate sends a message (WM_PAINT) requesting the view needs refreshed.
view.refresh actually calls the view draw method. -
@jhauswirth said:
Invalidate sends a message (WM_PAINT) requesting the view needs refreshed.
view.refresh actually calls the view draw method.Thanks for providing some behind the curtain info!
Is WM_PAINT not a Windows message? Is it present on both platforms?
So .invalidate make a request to refresh the view - but how is it determined that it actually will be refreshed? Is that SketchUp or the System? -
@unknownuser said:
The WM_PAINT message is generated by the system and should not be sent by an application. (source
@unknownuser said:
Most drawing carried out during processing of the WM_PAINT message is asynchronous; that is, there is a delay between the time a portion of the window is invalidated and the time WM_PAINT is sent. During the delay, the application typically retrieves messages from the queue and carries out other tasks. The reason for the delay is that the system generally treats drawing in a window as a low-priority operation and works as though user-input messages and messages that may affect the position or size of a window will be processed before WM_PAINT . (source
so .invalidate pushes WM_PAINT in message queue which will call the draw method from WindowProc sometime later and .refresh will immediately call the draw method.
too many .refresh will result in a slower workflow due unnecessary redraws instead of mixing all (system + code) in one draw.
-
@tig said:
I tend to use
begin > view.refresh > rescue > view.invalidate > end
to trap for <~v8.
a one-liner is possible when rescue is used in modifier position, it can take a single argument to return if an exception is raised:
view.refresh rescue view.invalidate
-
@unknownuser said:
too many .refresh will result in a slower workflow due unnecessary redraws instead of mixing all (system + code) in one draw.
Right - so if I make a wrapper that will refresh after a given max interval - otherwise invalidate - that would be an ok method?
<span class="syntaxdefault"><br />def update_view</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">view </span><span class="syntaxkeyword">)<br /> @</span><span class="syntaxdefault">last_refresh </span><span class="syntaxkeyword">||= </span><span class="syntaxdefault">Time</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">now<br /> </span><span class="syntaxkeyword">if </span><span class="syntaxdefault">Time</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">now </span><span class="syntaxkeyword">- @</span><span class="syntaxdefault">last_refresh </span><span class="syntaxkeyword">> </span><span class="syntaxdefault">0.2<br /> view</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">refresh<br /> </span><span class="syntaxkeyword">@</span><span class="syntaxdefault">last_refresh </span><span class="syntaxkeyword">= </span><span class="syntaxdefault">Time</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">now<br /> </span><span class="syntaxkeyword">else<br /> </span><span class="syntaxdefault">view</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">invalidate<br /> end<br />end<br /></span>
-
@unknownuser said:
so .invalidate pushes WM_PAINT in message queue which will call the draw method from WindowProc sometime later and .refresh will immediately call the draw method.
But isn't this specific to Windows?
-
@unknownuser said:
Right - so if I make a wrapper that will refresh after a given max interval - otherwise invalidate - that would be an ok method?
by using that you dont address the problem because you dont take in account system draw. but it can be used as workaround.
WM_PAINT is Windows specific, I didn't delved deeper in OSX internals yet. the main idea is - do not update the whole window if you just modified a small part of it - how we will implement that without Sketchup help, we will see
-
@unknownuser said:
@unknownuser said:
Right - so if I make a wrapper that will refresh after a given max interval - otherwise invalidate - that would be an ok method?
by using that you dont address the problem because you dont take in account system draw. but it can be used as workaround.
So skip the
view.invalidate
all together?
Advertisement