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.
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.
To add an item to a TListBox you can use one of the following methods.
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.
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);
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
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.
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';
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.
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.
- Now click Populate ListBox1 button. TListBox instance in Basic operations tab (ListBox1) will be populated like shown below.
- 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.
- Now let's delete selected item(s). First of course you have to select some items. Like show below.
- Now click Delete selected item(s) button. And the previously selected item will be deleted. Like shown below.
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.
BasicWorkingWithTListBox_Demo.zip 232.9KB 2155 downloads
Edited by LuthfiHakim, 31 December 2012 - 12:35 AM.