Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

The Basic Working with TListBox

tlistbox basic operation delphi freepascal lazarus control

  • Please log in to reply
2 replies to this topic

#1 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 29 December 2012 - 12:26 AM

Overview

TListBox is one of the most utilized controls in VCL-based Delphi applications. It usually used to show a list of items and allow user to select one or more item. Quick "mastery" over it will prove very advantageous for any Delphi coder.


In this tutorial I will show you basic working with TListBox.


Basic Operations

As with other kind of list or collection class, usually you will need to know at least the following operations.

  • Add item
  • Find item
  • Remove item
  • Update item

Item in this context is a string. But the string could be accompanied/associated with an object which capable to provide extended information. We will cover this mainly on "Advanced Operations" article later.

Since TListBox is a control, which main use is to provide interface to users, it has additional basic operations you need to know.

  • Detect or get selected item(s)
  • Select or unselect item(s)
  • Detect focused item
  • Set focused item


Beside these basics operations, there are some advance operations you can do with TListBox. Some of them:

  • Custom coloring of items. Here you could have different item to have different color. Both the background and font color. You could even be overly "creative" by showing each character in different background and font color (I really don't recommend this, though).
  • Dragging item(s) to change position (in same TListBox).
  • Dragging items(s) to another TListBox.

We will cover these advance operations in another tutorial.


Add Item

To add an item to a TListBox you can use one of the following methods.
  • TListBox.AddItem
  • TListBox.Items.Add
  • TListBox.Items.AddObject

Method TListBox.AddItem requires a string and an object to be associated with the string. If you don't want to use the string-to-object association, just pass nil for the object parameter. This method actually the same with TListBox.Items.AddObject. You can use them interchangeably without problem.

While TListBox.AddItem is exactly the same with TListBox.Items.AddObject, TListBox.Items.Add is the same with TListBox.AddItem if you pass nil for the object. So when you don't want string-to-object association you could consider using this method.

The advantage of adding item using methods from TListBox's Items property is that we get the index of the added item. This index can be used for quick finding the item in the list. We will cover this shortly.


Code sample

In the following codes we will add 3 items, i.e. "Item 1", "Item 2", and "Item 3" to a TListBox named ListBox1. Note that none of them use string-to-object association. We will cover it in advance section.

  ListBox1.AddItem('Item 1', nil);
  ListBox1.Items.Add('Item 2');
  ListBox1.Items.AddObject('Item 3', nil);


Find Item

After you have added several items, you may want to find the position of certain item. Of course you may store the indexes everytime you do the addition. But it is not practical if you don't need extremely fast way to find your items. To find the index/position of an item, you call TListBox.Items.IndexOf method. Something like this:

  vMyItemIndex := ListBox1.Items.IndexOf('My Item');
  // vMyItemIndex will now contain index of 'My Item' string
  // in ListBox1. If it's -1, then 'My Item' was not found.

If you want to find items using objects associated to them, then you call TListBox.Items.IndexOfObject method. Something like this:

var
  vMyObj: TObject;
begin
  // initiate vMyObj to contain reference to the object
  // associated with 'My Item'
  vMyObject := ...;

  vMyItemIndex := ListBox1.Items.IndexOfObject(vMyObject);
  // vMyItemIndex will now contain index of item associated
  // with object referenced in vMyObject
  ...
end;

In the case the item or the associated object was not found, these methods return -1. Now you know that you can check against this value to see whether the item was found or not. Personally I like to wrap these method in easier to read functions, like in the followings. The codes should be declared in a descendant of TListBox, and in our example we named it TMyListBox.

function TMyListBox.FindItem(const AItem: string; var AIndex: Integer): Boolean;
begin
  AIndex := Self.Items.IndexOf(AItem);
  Result := AIndex > -1;
end;

With the above method, you can write codes like this:

  if MyListBox1.FindItem('My Item', i) do
    ...  // do things you should do if the item was found
  else
    ...  // do things you should do when the item was not found


Remove Item

In some occasions you need to delete item(s) in a TListBox. Accomplish this using method TListBox.Items.Delete method. But note that that method requires index of the item to be deleted. You can get this information either by storing returned indexes when adding items (using TListBox.Items.AddObject or TListBox.Items.Add), or you can find the index by using methods explained in the previous section.

Once you have the index, pass it to TListBox.Items.Delete, and the item will be deleted. Something like this.

  // will delete 'My Item' string if exists in ListBox1
  i := ListBox1.Items.IndexOf('My Item');
  if i > -1 do
    ListBox1.Delete(i);

Note that deleting an item will not automatically free/destroy associated object. So if you have object associated with the deleted item, you need to employ another method to make sure the object will not becoming memory leak.


Update Item

You can change or update the string you already added to a TListBox to make it show different text in the item's place. Like with removing items, you need to have the index or the position of the item before you can update it. So execute one of the methods explained in Find Item section to get the index, then use the TListBox.Items.Strings property to change the item's actual text. This property is an array property. So pass the index to specify which array member to be changed. Something like the followings.

  // the following codes will change 'My Item' into 'My New Item'
  vMyItemIndex := ListBox1.Items.IndexOf('My Item');
  if vMyItemIndex > -1 then
    ListBox1.Items.Strings[vMyItemIndex] := 'My New Item';

You can shorten the following line

    ListBox1.Items.Strings[vMyItemIndex] := 'My New Item';

into

    ListBox1.Items[vMyItemIndex] := 'My New Item';

This is possible because Strings is default property of TStrings (the class of TListBox.Items).


Detect of Get Selected Item(s)

Other that just viewing, once users have been presented with a list of item they should be able to select one or more item. And how do we get the selected item(s) from a TListBox? Unfortunately there is no direct way to get it. You have to iterate all the items and check whether they are selected or not using TListBox.Selected array property.

You can use codes like below. Note that the sample procedure will populate the supplied TStrings instance with items and associated objects currently selected in the specified TListBox.

procedure GetSelectedItems(AListBox: TListBox; AList: TStrings);
var
  i: Integer;
begin
  AList.Clear;
  for i := 0 to AListBox.Items.Count-1 do
    if AListBox.Selected[i] then
      AList.AddObject(AListBox.Items[i], AListBox.Items.Objects[i]);
end;


Select or Unselect Item(s)

Beside detect item(s) selected by user action, you can select (or unselect) items using codes. Same like detecting selected items, here you will use the Selected array property. To select an item, just pass its index to the array property and set the corresponding boolean value to true. To unselect pass boolean value of false.

For example, to select all items:
  for i := 0 to ListBox1.Count-1 do
    ListBox1.Selected[i] := True;

or to unselect all items:
  for i := 0 to ListBox1.Count-1 do
    ListBox1.Selected[i] := True;

In the demo project there is an example which randomly select items in a listbox.


Detect Focused Item

You can detect item that currently focused using the TListBox's ItemIndex property. As the name suggested, this property indicates the index of focused item. If that property has value 0 or larger, then there is a focused item. When it has -1 value, then there is no focused item. To actually get the item, you must combine this property with Items property. Something like shown below.

 var
   ..
   vFocusedItem: string;
   ..
 begin
   ..
   vFocusedItem := ListBox1.Items[ListBox1.ItemIndex];
   ..
 end;

Note that the sample code above does not check for whether there is focused item.


Set Focused Item

To change the focused item, just set the ItemIndex property to the index of the item you want to be focused on. Something like this.

  // focus the first item
  ListBox1.ItemIndex := 0;

  // focus the last item
  ListBox1.ItemIndex := ListBox1.Count-1;

Note that focused item does not necessarily selected. When focus change was caused by user actions(clicking mouse or using arrow buttons), the focused item will automatically selected. But if the change was done through code like we show here, the focused item will not necessarily selected. If it has to also be selected, you must add code to select it.


Demo Project

I have written a demo project to show you the basic operations. Actually it contains some code samples for advance operations. But we won't discuss it here. Feel free to examine the codes for advance operation, however.


  • Upon running the demo project you will be presented with display like shown below.

    BasicWorkingWithTListBox_Runtime_00.png

  • Now click Populate ListBox1 button. TListBox instance in Basic operations tab (ListBox1) will be populated like shown below.

    BasicWorkingWithTListBox_Runtime_01_ListBoxPopulated.png

  • Click Clear button and ListBox1 content will dissapear.
  • Click again Populate ListBox1 button so we have some items to work with.
  • Select a few items. You can select first item by simple click on it and use Ctr+Click to select another item. If you want to select a range of items, you can click the first item and then Shift+click on the item of the other end of the range.
  • After a few items have been selected, click on Show selected item, and you will be presented with a dialog showing text of all selected items. Something like shown below.

    BasicWorkingWithTListBox_Runtime_02_GetSelectedItems.png

  • Now let's delete selected item(s). First of course you have to select some items. Like show below.

    BasicWorkingWithTListBox_Runtime_04_SelectItemsToDelete.png

  • Now click Delete selected item(s) button. And the previously selected item will be deleted. Like shown below.

    BasicWorkingWithTListBox_Runtime_05_SelectedItemsDeleted.png

You can continue on your own to explore the rest of the operations. If you stumble into any problem, feel free to post the problem here.

Attached File  BasicWorkingWithTListBox_Demo.zip   232.9KB   2109 downloads

Edited by LuthfiHakim, 31 December 2012 - 12:35 AM.

  • 1

#2 SillyOldDragon

SillyOldDragon

    CC Lurker

  • Just Joined
  • Pip
  • 1 posts

Posted 19 September 2014 - 03:26 PM

Very nicely done and very useful.

 

I would like to see the advanced topics cover:

     adding more columns, loading to them and showing the contents

     finding out what the highest item index is before and after adding a new record

 

I'm doing fine with loading one field with the contents of an array and showing the contents of a selected item in a ShowMessage

box.


Edited by SillyOldDragon, 19 September 2014 - 03:30 PM.

  • 1

#3 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 22 September 2014 - 03:54 PM

Thanks! The columns subject might be interesting. I will see if I can find some time to write it. But I don't know about the item index related issues, since the solution was pretty obvious and straightforward (just use the Items.Count-1, before and after adding item).

 

Actually I forgot that I haven't explained content in Tab "Advance operation" :)


  • 0





Also tagged with one or more of these keywords: tlistbox, basic operation, delphi, freepascal, lazarus, control

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download