[Lazarus] TreeView sometimes calls Refresh instead of Invalidate

cobines cobines at gmail.com
Thu Mar 29 23:25:38 CEST 2012


Hello.

In the TreeView there are many calls to TreeView.Invalidate but
TTreeNodes.SetUpdateState and TTreeStrings.SetUpdateState call
TreeView.Refresh instead. Refresh calls TWidgetSet.UpdateWindow which
on Win32 and GTK2 causes repaint of the control via synchronous
WM_PAINT. QT4 seems to only post a paint request to the message queue.
Should it not be Invalidate instead of Refresh? Why the need for
immediate Repaint? Multiple calls to Invalidate stack, so only one
Paint is done later.

At least on Windows and GTK2 this causes the TreeView to be repainted
twice instead of once:

TreeView1.Items.Add(nil, 'Something');


There seem to be redundant Invalidates as well. For example in
TTreeNodes.InternalAddObject TreeView is invalidated after adding
node:

...
    Result.InternalMove(Node,AddMode);
...
    if (FUpdateCount=0) and (Owner<>nil) then
      Owner.Invalidate;


But in TTreeNode.InternalMove there is already call to
TreeView.EndUpdate in which there is:

  Items.EndUpdate;
  if Items.FUpdateCount=0 then begin
    // ToDo: only refresh if something changed
    UpdateScrollBars;
    Invalidate;
  end;

Items.EndUpdate causes repaint via UpdateWindow. Then there's
Invalidate which will post another WM_PAINT to the message queue. And
finally there's yet another Invalidate when it goes back to
TTreeNodes.InternalAddObject, as shown above.

Similar thing is within TTreeNodes.Clear.

  BeginUpdate;
...
    if (FUpdateCount = 0) and Assigned(Owner) then
      Owner.Invalidate;
...
  EndUpdate;

The Owner.Invalidate is redundant, since EndUpdate will call
Owner.Refresh anyway. Plus it will never be called anyway since we
just increased FUpdateCount with BeginUpdate.

There are three more instances where Invalidate is called within
Begin/EndUpdate block or just after EndUpdate.
Are the explicit calls to Invalidate needed?

--
cobines




More information about the Lazarus mailing list