[Lazarus] How to fix slow screen refresh of TListbox?

Bo Berglund bo.berglund at gmail.com
Sat Nov 12 09:33:51 CET 2022


On Fri, 11 Nov 2022 23:37:14 +0100, Bo Berglund via lazarus
<lazarus at lists.lazarus-ide.org> wrote:

Concerning TSynEdit:

>I have a couple of questions:
>
>1) Is there a way to make sure that when adding text to synedit the view 
>shifts such that the last line is visible?
>I.e. Automatically scroll the text up when new text is added....

This was my most acute problem with the synedit object, but see below...

>2) The reason I am not adding incoming data to the listbox as they arrive is
>that I don't know if the serial component provides the data at line endings or
>in the middle of a line, so I add the data to the old data in the TBytes array
>and then dump the content of the TBytes into the text property of the box.

I have dug down into the serial component and found that it actually dumps data
at a rather high pace with small packets every time...

Example:
One transmission contains 16 lines of data totalling 1130 bytes, but the serial
port component triggered an ondata event for a lot less, more like less than 10
bytes so the transmission triggered a big number of events, each updating the
listbox which totally overloaded the system.

So now I have changed two properties on the serial component:
- ReadPacketSize := 1500 (default is 16)
- ReadTimeout := 200 (default is 2 ms)

Since most transfers are shorter than 1500 the timeout of 200 ms will trigger
and by then the complete message *is* available, hence only one call to update
the screen display with new text.
This helps to make it more responsive...

>What happens if one adds the text as a block to this synedit where the block
>does not end in a line feed?
>Will the end of it be some way into the last line such that if I then add the
>next transmission it will start at that position and not on a new line?

It is my belief that even though there is no data following the end of the last
line (like an explicit linefeed), the next data added will start on a new
line...

Unless of course one could do the following (pseudocode):

synedit.lines[lastline] := synedit.lines[lastline] + incomingdata;

This would extend the last line with the incoming data...

>
>If that is possible then the handling will become a lot easier since I just have
>to add the few new lines at the end directly in synedit...

No just simply adding incoming data to the lines does not work, they will start
on a new line (see above)...


>But how to jump to the end of the text on screen?

Right now this was my one remaining issue, since the Lines property does not
have a settable "ItemIndex" value that will move a line into the visible area.

But I found out that there is another useful property:

synRxData.CaretY := synRxData.Lines.Count;

This tries to put the cursor 1 line beyond the end and it does exactly what I
need to do by showing the incoming new data and scrolling up the display
visibly.
This is how it is now done in full:

  SetLength(DataTxt, Length(DataBuffer)); //Set string length
  Move(DataBuffer[0], DataTxt[1], Length(DataBuffer)); //Copy data to string
  {$ifdef USESYNEDIT}
    synRxData.Lines.Beginupdate;
    synRxData.Lines.Text := DataTxt;
    synRxData.CaretY := synRxData.Lines.Count;
    synRxData.Lines.Endupdate;
  {$else}
    lbxRxData.Items.Beginupdate;
    lbxRxData.Items.Text := DataTxt;
    lbxRxData.ItemIndex := lbxRxDataBak.Items.Count -1;
    lbxRxData.Items.Endupdate;
  {$endif}


-- 
Bo Berglund
Developer in Sweden



More information about the lazarus mailing list