Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

TListView jumpy when using TImageList 1

Status
Not open for further replies.

djjd47130

Programmer
Nov 1, 2010
480
US
I have a TListView where I'm loading hundreds of items. Every item has its own unique corresponding image. First, I populate the TListView with an item for every record that belongs, with no images. Then, I loop through those items, identify the appropriate image to load for that item, and save that image into the TImageList which is then mapped to the TListView. However, with every little change I do to the TImageList, the entire TListView refreshes, thus flashing the display. Specifically, every time I add a TBitmap to the TImageList, the TListView automatically refreshes every single icon. How do I prevent this, to keep the TListView from flashing drastically when loading the pictures? Currently I first un-assign the TImageList from the TListView so it doesn't refresh, then when done, re-assign it back again. But I'd like the images to show as it loads, just not flash real fast.

JD Solutions
 
Thanks, I tried the DoubleBuffered properties, and didn't help much.

JD Solutions
 
Double buffering, while a good idea, won't solve this.

Your problem is similar to the flicker problem that you get in TMemo or other string controls. Something gets added to the String List, redraw message is fired, the whole control is redrawn.

This is what is happening to your TListView. To solve it, you will have to come up with similar functionality in some way to BeginUpdate/EndUpdate as a descendant to TImageList (if not already there) or make provision for it in your TListView code by blocking this redraw message while you are adding images. Studying the VCL source for these objects should reveal particulars of what to do.

As a help since I see a little when I look at help for these objects, when TImageList is a supplicant object, it sends LVM_SETIMAGELIST to the TListView upon adding an image. If you go the TListView route to block the message, look into TListView.WindowProc.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
You haven't indicated that you have answered this, so I did some playing around. Actually, BeginUpdate/EndUpdate is your solution, or rather the easier one, since it does the same as described above.

Code:
procedure TForm1.Button2Click(Sender: TObject);
// builds the TListView.  PR assigns an image out of the ImageList to each.
var
  NewColumn: TListColumn;
  NewItem: TListItem;
  i: integer;
begin
  Button2.Enabled := false;
  ListView1.Columns.BeginUpdate;
  ListView1.Columns.Clear;
  with ListView1 do
    begin
      ViewStyle := vsReport;
      RowSelect := true;
      MultiSelect := false;
      NewColumn := Columns.Add;
      NewColumn.Caption := 'Item Listing';
      NewColumn.Width := -2;
    end;
  ListView1.Columns.EndUpdate;
  ListView1.Items.BeginUpdate;
  ListView1.Items.Clear;
  for i := 1 to 2000 do
    begin
      NewItem := ListView1.Items.Add;
      NewItem.Caption := IntToStr(i);
      NewItem.ImageIndex := Random(ImageList1.Count);
    end;
  ListView1.Items.EndUpdate;
  Button2.Enabled := true;
end;

I've pushed a large number of images through this and noticed no flicker. Calling Application.ProcessMessages will also produce flickering when I test.

Hope this helps solve what you are noticing.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
If you want it draw more gradually instead of all at once, this will work:
Code:
if i mod 1000 = 0 then  // draws roughly every 1000 loops
  begin
    ListView1.Items.EndUpdate;
    Application.ProcessMessages;
    ListView1.Items.BeginUpdate;
  end;

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Thanks Glenn. I use those methods with the DevExpress components and didn't even think of using those with a standard component.
 
Thank you, that's definitely a great help, but I've started a more customized component - I'm (for the sake of a challenge) building a list component similar to both the TStringGrid and TListView together - inherited from a TScrollingWinControl. I'm literally reading the OnMouseMove event to recognize when the mouse is pointed over certain "Hotspots" (or range of pixels) and doing proper handling if so. Actually, although extremely difficult, it's also very flexible. I know for a fact it won't try to draw its self without me telling it to.

This would be the 3rd component I've built based on the TScrollingWinControl.


JD Solutions
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top