Open gasensorX opened 2 years ago
I took a look at the ListBox, unfortunately this seems to be quite complicated. I can't even manage to fill the ListBox with items. I've also tried using PCollection with no success.
The way you write, you've already managed to do something, which unfortunately caused a crash. If you could post this snippet of code, maybe we can work something out together.
Here is my attempt:
constructor TMyDialog.Init;
var
Rect: TRect;
sb: PScrollBar;
ListBox: PListBox;
pc: PCollection;
ps: PString;
begin
Rect.Assign(0, 0, 42, 21);
Rect.Move(23, 3);
inherited Init(Rect, 'Mein Dialog');
// ListBox
Rect.Assign(5, 5, 7, 15);
sb := new(PScrollBar, Init(Rect));
pc := new(PCollection, Init(4, 4));
pc^.Insert(NewStr('abc'));
pc^.Insert(NewStr('abc'));
pc^.Insert(NewStr('abc'));
pc^.Insert(NewStr('abc'));
Rect.Assign(5, 2, 31, 15);
ListBox := new(PListBox, Init(Rect, 3, nil));
// ListBox^.NewList(pc);
// ps:=new(PString);
// ps^:='abcd';
// ListBox^.Insert(ps);
// ListBox^.Insert(ps);
ps := newstr('dsfdsfdsf');
// ListBox^.List^.Insert(ps);
ListBox^.Insert(pc);
//ListBox^.Insert(PString, Init('hallo'));
//ListBox^.Insert(PString, Init('hallo'));
Insert(ListBox);
// Button, bei den der Titel geändert wird.
Rect.Assign(19, 18, 32, 20);
CounterButton := new(PButton, Init(Rect, ' ', cmCounter, bfNormal));
CounterButton^.Title^ := '1';
Insert(CounterButton);
// Ok-Button
Rect.Assign(7, 18, 17, 20);
Insert(new(PButton, Init(Rect, '~O~K', cmOK, bfDefault)));
end;
This is my test code. Hope that helps.
Lazarus Forum: https://forum.lazarus.freepascal.org/index.php?topic=59237.msg441632#msg441632
Test code https://forum.lazarus.freepascal.org/index.php?action=dlattach;topic=59237.0;attach=48955
thanks for the code All I had to do was {H-} and it compiled and ran with Fehlerfrau. This was because of the string, as FV requires ShortString. I haven't looked yet because of MemoryLeaks, but at least there is an entry in the ListBox.
With the following code even 4.
pstr := NewStr(s);
PPortStrList^.Insert(pstr);
PPortStrList^.Insert(NewStr('abc'));
PPortStrList^.Insert(NewStr('def'));
PPortStrList^.Insert(NewStr('1234'));
I didn't think of PStringCollection, as you can see it's been a few lines since I wrote the tutorial.
Not only PListBox and PSortedList Box are worth a tutorial, but also PStringCollection.
I wrote my tutorial based on an old Turbo Pascal book, and therefore almost exclusively used components that I found there.
Another tip that will make your code more readable, please do not use "P" in front of the variable names:
Poorly:
PSpeedStrList: PStringCollection;
PPortStrList: PStringCollection;
PEditPort: PInputLine;
PEditSpeed: PInputLine;
PRadioButtonBytes: PRadioButtons;
PRadioButtonPairty: PRadioButtons;
Good:
SpeedStrList: PStringCollection;
PortStrList: PStringCollection;
EditPort: PInputLine;
EditSpeed: PInputLine;
RadioButtonBytes: PRadioButtons;
RadioButtonPairty: PRadioButtons;
Another question, what are you developing with? Your code doesn't look like Lazarus komfom. Are you using the FPC IDE running in the console.
And one more thing, what OS are you using?
Ein erster Versuch, scheint zu klappen.
https://github.com/sechshelme/Lazarus-FreeVision/tree/master/99_Test/10_ListBox
Define pointer variable names using "P" as the prefix in order to avoid misuse.
I use fp and Lazarus at the same time. And I work under Linux OS.
I edit the "10_ListBox" to adding Heap display. I find it is still memory leaking.
Strings created by NewStr() can not automatic free/dispose.
I took a closer look at the sources of "PListBox". In my opinion, a destructor is missing there, which "list" cleans up.
TListBox = OBJECT (TListViewer)
List: PCollection; { List of strings }
CONSTRUCTOR Init (Var Bounds: TRect; ANumCols: Sw_Word;
AScrollBar: PScrollBar);
CONSTRUCTOR Load (Var S: TStream);
// Failure Destructor
FUNCTION DataSize: Sw_Word; Virtual;
I tried the following, but then the whole program crashes.
type
PNewListBox = ^TNewListBox;
TNewListBox = object(TListBox)
destructor Done; virtual;
end;
.....
destructor TNewListBox.Done;
begin
FreeAll;
inherited Done;
end;
I also find that a bit strange, if the ListBox is empty, why is an insert simply ignored and no new ones are created.
procedure TListBox.Insert (Item : Pointer);
begin
if (List <> nil) then
begin
List^.Insert(Item);
SetRange(List^.Count);
end;
end;
This is weird too, you can't even remove an entry without it popping.
StringCollection := new(PCollection, Init(2, 1));
StringCollection^.Insert(NewStr('Montag'));
StringCollection^.Insert(NewStr('Dienstag'));
StringCollection^.Insert(NewStr('Mittwoch'));
StringCollection^.Insert(NewStr('Donnerstag'));
StringCollection^.Insert(NewStr('Freitag'));
StringCollection^.Insert(NewStr('Samstag'));
StringCollection^.Insert(NewStr('Sonntag'));
Rect.Assign(5, 2, 31, 7);
ListBox := new(PListBox, Init(Rect, 1, ScrollBar));
ListBox^.NewList(StringCollection);
Insert(ListBox);
ListBox^.Insert(NewStr('aaaaaaaaa'));
ListBox^.FreeItem(1); // Knall !!
Anything that has anything to do with deleting an entry in the ListBox causes the program to crash.
All of the following variants make a bang.
// ListBox^.FreeItem(2);
// StringCollection^.AtFree(ListBox^.Focused);
// ListBox^.List^.AtFree(ListBox^.Focused);
The problem must definitely be with the TListBox. The only thing I do in the dialog now is fill a StringCollection and then release it with Dispose. There are no storage corpses here.
constructor TMyDialog.Init;
var
Rect: TRect;
i: Sw_Integer;
const
Tage: array [0..6] of shortstring = (
'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag');
begin
Rect.Assign(10, 5, 67, 17);
inherited Init(Rect, 'ListBox Demo');
// StringCollection
StringCollection := new(PStringCollection, Init(2, 1));
for i := 0 to Length(Tage) - 1 do begin
StringCollection^.Insert(NewStr(Tage[i]));
end;
Dispose(StringCollection, Done);
exit;
If I do the following, I get a memory corpse. Although I didn't even fill the list with dates.
begin
Rect.Assign(10, 5, 67, 17);
inherited Init(Rect, 'ListBox Demo');
ListBox := new(PListBox, Init(Rect, 1, nil));
Dispose(ListBox, Done);
exit;
If I do the same with a PButton, the memory is cleaned up cleanly. I even tried it with a filled PRadioButtons, all clean.
I soon suspect that there is a bug in PListBox.
bt := new(PButton, Init(Rect, '~T~ag', cmTag, bfNormal));
Dispose(bt, Done);
exit;
rad := New(PRadioButtons, Init(Rect, NewSItem('~G~ross', NewSItem('~M~ittel', NewSItem('~K~lein', nil)))));
Dispose(rad, Done);
exit;
I took a closer look at the TFileListBox used by the TFileDialog. Then I came across the following:
destructor TFileList.Done;
begin
if List <> nil then Dispose(List, Done);
TListBox.Done;
end;
They added their own destructor there.
Now I also built a new ListBox and added a destructor and used this ListBox in my dialog. As it seems, this works. the memory leak is gone.
I'll make a few more tries. In my opinion, this is a bug in TListBox, which lacks the destructor.
type
PNewListBox = ^TNewListBox;
TNewListBox = object(TListBox)
destructor Done; virtual;
end;
...
destructor TNewListBox.Done;
begin
if List <> nil then begin
Dispose(List, Done);
end;
TListBox.Done;
end;
constructor TMyDialog.Init;
var
Rect: TRect;
ScrollBar: PScrollBar;
i: Sw_Integer;
const
Tage: array [0..6] of shortstring = (
'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag');
begin
Rect.Assign(10, 5, 67, 17);
inherited Init(Rect, 'ListBox Demo');
// StringCollection
StringCollection := new(PStringCollection, Init(5, 5));
for i := 0 to Length(Tage) - 1 do begin
StringCollection^.Insert(NewStr(Tage[i]));
end;
// ScrollBar für ListBox
Rect.Assign(31, 2, 32, 7);
ScrollBar := new(PScrollBar, Init(Rect));
Insert(ScrollBar);
// ListBox
Rect.Assign(5, 2, 31, 7);
ListBox := new(PNewListBox, Init(Rect, 1, ScrollBar));
ListBox^.NewList(StringCollection);
Insert(ListBox);
// Cancel-Button
Rect.Assign(19, 9, 32, 10);
Insert(new(PButton, Init(Rect, '~T~ag', cmTag, bfNormal)));
// Ok-Button
Rect.Assign(7, 9, 17, 10);
Insert(new(PButton, Init(Rect, '~O~K', cmOK, bfDefault)));
end;
https://forum.lazarus.freepascal.org/index.php/topic,59237.0/topicseen.html
updated
lazarus/freepascal offical reply
So, now a tutorial for ListBoxes has been added. With the ListBoxes, you can manually remove the loaded list from memory. This is described in the tutorial.
There is missing a TListBox Tutorial. It is useful.
I tried to use TListBox, but a memory leak always occurred.
Can you add a simple example for TListBox?
TKS