Mike Littlewood
asked on
Im missing the connection between the objects, can someone point me in the right direction.
Should be a fairly easy solutioin but I must be missing something obvious.
Ive got a new class created
TCBRecord = class
private
Variable1, Variable2, etc
<Procedures to set variables, functions to read>
public
<Constructor>
<read/write properties>
end
TMyForm = class(TForm)
MyBook : TList
I create a TCBRecord and then add it to MyBook
The thing is that MyBook is not linked to TCBRecord, but to the form it is on.
Im trying to now read the entries from MyBook but I cant access the records.
Obvisouly Im putting the variables in the wrong places but I cant see how to re-arrange things.
The TList must be linked to the form as I want to try and read variables from the records in MyList to display in a stringgrid
Why cant I do
For iCnt := 0 to (MyBook.Count - 1) do
begin
Stringgrid.Cells[Col, Row] := MyBook[iCnt].variable1
end
So MyBook[iCnt].variable1 is incorrect, how can I now access the data
Ive got a new class created
TCBRecord = class
private
Variable1, Variable2, etc
<Procedures to set variables, functions to read>
public
<Constructor>
<read/write properties>
end
TMyForm = class(TForm)
MyBook : TList
I create a TCBRecord and then add it to MyBook
The thing is that MyBook is not linked to TCBRecord, but to the form it is on.
Im trying to now read the entries from MyBook but I cant access the records.
Obvisouly Im putting the variables in the wrong places but I cant see how to re-arrange things.
The TList must be linked to the form as I want to try and read variables from the records in MyList to display in a stringgrid
Why cant I do
For iCnt := 0 to (MyBook.Count - 1) do
begin
Stringgrid.Cells[Col, Row] := MyBook[iCnt].variable1
end
So MyBook[iCnt].variable1 is incorrect, how can I now access the data
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thx to u both for your answers.
Is a TList better to use for say simple lists like strings and integers.
While TObjectList is better for holding objects.
Im gonna award the points to Russell as he did answer my question and solve the issue I had.
But thanks for that complete answer Shane, I think I might re-write the section and create another new class.
Im sorta trying new things out so I appreciate the complete answer.
Is a TList better to use for say simple lists like strings and integers.
While TObjectList is better for holding objects.
Im gonna award the points to Russell as he did answer my question and solve the issue I had.
But thanks for that complete answer Shane, I think I might re-write the section and create another new class.
Im sorta trying new things out so I appreciate the complete answer.
ASKER
In fact I split the points for you both
thanks again
thanks again
Tlist is good for record pointers, integers, pointers in general; basically anything that is not a TObject decendant. The object list provides a better means for handling objects. Even better (in this case) would have been to create a TCollection and TCollectionItem class setup.
It just depends how much extra work you wish to put into it, and if you do/don't mind handling the memory management yourself.
Thanks for the pts,
Russell
ASKER
>>Even better (in this case) would have been to create a TCollection and TCollectionItem class setup. <<
Don't mean to be a pain asking too many basic questions, but could you give me some logic as to why this would be better.
It doesnt help that I havent used TCollection before, maybe once I get the full program running how I want it I might do some more experimenting
Don't mean to be a pain asking too many basic questions, but could you give me some logic as to why this would be better.
It doesnt help that I havent used TCollection before, maybe once I get the full program running how I want it I might do some more experimenting
Yeah, i'd like to hear how this would be better also
listening....
Shane
listening....
Shane
ASKER
Hey Shane, got another quick question for ya .. following on from the large section you wrote.
I seem to be having some problems getting the correct record out of my TObjectList.
Ive created that wrapper you suggested around my TCBRecord
Not sure if this is correct but ...
Im reading the records from a database into my TCBRecord in a loop and adding to my ObjectList (TMyList)
Temp_CBRecord := TCBRecord.create;
while <Something> do
begin
Temp_CBRecord.VALUE1 := IBQuery.FieldByName('VALUE 1').AsStri ng;
Temp_CBRecord.VALUE2 := IBQuery.FieldByName('VALUE 2').AsStri ng;
<etc>
MyList.Add(Temp_CBRecord);
IBQuery.next
end;
but when I try to access the records outside of this procedure, I only ever seem to read the last entry into the list
at a guess Im saying I shouldnt be adding temporary records to MyList
for RecordIndex:= 0 to (MyList.Count - 1) do
ReadTCBRecordAndDoSomethin g(RecordIn dex);
I seem to be having some problems getting the correct record out of my TObjectList.
Ive created that wrapper you suggested around my TCBRecord
Not sure if this is correct but ...
Im reading the records from a database into my TCBRecord in a loop and adding to my ObjectList (TMyList)
Temp_CBRecord := TCBRecord.create;
while <Something> do
begin
Temp_CBRecord.VALUE1 := IBQuery.FieldByName('VALUE
Temp_CBRecord.VALUE2 := IBQuery.FieldByName('VALUE
<etc>
MyList.Add(Temp_CBRecord);
IBQuery.next
end;
but when I try to access the records outside of this procedure, I only ever seem to read the last entry into the list
at a guess Im saying I shouldnt be adding temporary records to MyList
for RecordIndex:= 0 to (MyList.Count - 1) do
ReadTCBRecordAndDoSomethin
We need tos ee this part
ReadTCBRecordAndDoSomethin g(RecordIn dex);
Shane
ReadTCBRecordAndDoSomethin
Shane
I think we can all agree on the following:
TList - list for maintiaing generic pointers
TObject - list that is specialized for holding generic objects, but still requires casting to the correct object type in order to use it.
The TCollection is similar to the object list, but offers the
following enhancements.
1.) Takes minimal coding to hande the adding/deleting/casting, as most of this functionality is already encapsulated in the TCollection / TCollectionItemClass.
2.) Can be persisted (because it inherits from TPersistent), which is useful for making this a property of a component, as it also offers a designer.
3.) If you free an object in an object list, you must code the removal from the object list. eg
obj:=TObjectList[1];
obj.Free; // TObjectList now holds a stale pointer at index 1
// The list must now be corrected to remove the item at index 1, because it was
// freed
The collection item on the other hand, will notify the collection of the removal so the developer can feel "free" (so to speak) to call Free on any object in the list, and not have to worry about the list management. Believe it or not, this scenario tends to catch quite a few developers...
So, using your example class, this is all that is required to turn this into a collection/collection item class set.
type
TCBRecord = class(TCollectionItem)
private
FVariable1: Integer;
FVariable2: Integer;
published
property Variable1: Integer read FVariable1 write FVariable1;
property Variable2: Integer read FVariable2 write FVariable2;
end;
type
TCBRecords = class(TCollection)
private
function GetItem(Index: Integer): TCBRecord;
procedure SetItem(Index: Integer; Value: TCBRecord);
public
constructor Create;
function Add: TCBRecord;
property Items[Index: Integer]: TCBRecord read GetItem write SetItem; default;
end;
implementation
function TCBRecords.Add: TCBRecord;
begin
result:=TCBRecord(inherite
end;
function TCBRecords.GetItem(Index: Integer): TCBRecord;
begin
result:=TCBRecord(inherite
end;
procedure TCBRecords.SetItem(Index: Integer; Value: TCBRecord);
begin
inherited SetItem(Index, Value);
end;
constructor TCBRecords.Create;
begin
inherited Create(TCBRecord);
end;
-------------
Anyways, it just provides a more tightly coupled way of managing same type objects, not to say that it could not have been done with TObjectList.
Russell
Example of use:
var cbRecords: TCBRecords;
begin
cbRecords:=TCBRecords.Crea te;
with cbRecords.Add do
begin
Variable1:=10;
Variable2:=20;
end;
Assert(cbRecords.Count = 1, 'Incorrect count');
cbRecords[0].Free;
Assert(cbRecords.Count = 0, 'Incorrect count');
cbRecords.Free;
var cbRecords: TCBRecords;
begin
cbRecords:=TCBRecords.Crea
with cbRecords.Add do
begin
Variable1:=10;
Variable2:=20;
end;
Assert(cbRecords.Count = 1, 'Incorrect count');
cbRecords[0].Free;
Assert(cbRecords.Count = 0, 'Incorrect count');
cbRecords.Free;
ASKER
Hi Shane
In the procedure I call I am just writing the info being held in the records to a stringrid
Following on from before:-
for RecordIndex:= 0 to (MyList.Count - 1) do
ReadTCBRecordAndDoSomethin g(RecordIn dex);
procedure ReadTCBRecordAndDoSomethin g(RecordIn dex: integer);
begin
Cells[Col1,Selected_Row] := MyList[RecordIndex].Value1 ;
Cells[Col2,Selected_Row] := MyList[RecordIndex].Value2 ;
Cells[Col3,Selected_Row] := MyList[RecordIndex].Value3 ;
<etc>
Inc(Selected_Row)
end
Im hoping this should loop through the TObjectList and write the values to the grid.
The issue is that it only ever seems to read the last record from the TObjectList,
whatever index value I use for MyList it contains the same data, the last record entered
into the list. Its almost like the last record is repeated at every index, like it overwrote
previous data for some reason.
Temp_CBRecord := TCBRecord.create;
while <Something> do
begin
Temp_CBRecord.VALUE1 := IBQuery.FieldByName('VALUE 1').AsStri ng;
Temp_CBRecord.VALUE2 := IBQuery.FieldByName('VALUE 2').AsStri ng;
<etc>
MyList.Add(Temp_CBRecord);
IBQuery.next
end;
is where I populated the TObjectList.
In the procedure I call I am just writing the info being held in the records to a stringrid
Following on from before:-
for RecordIndex:= 0 to (MyList.Count - 1) do
ReadTCBRecordAndDoSomethin
procedure ReadTCBRecordAndDoSomethin
begin
Cells[Col1,Selected_Row] := MyList[RecordIndex].Value1
Cells[Col2,Selected_Row] := MyList[RecordIndex].Value2
Cells[Col3,Selected_Row] := MyList[RecordIndex].Value3
<etc>
Inc(Selected_Row)
end
Im hoping this should loop through the TObjectList and write the values to the grid.
The issue is that it only ever seems to read the last record from the TObjectList,
whatever index value I use for MyList it contains the same data, the last record entered
into the list. Its almost like the last record is repeated at every index, like it overwrote
previous data for some reason.
Temp_CBRecord := TCBRecord.create;
while <Something> do
begin
Temp_CBRecord.VALUE1 := IBQuery.FieldByName('VALUE
Temp_CBRecord.VALUE2 := IBQuery.FieldByName('VALUE
<etc>
MyList.Add(Temp_CBRecord);
IBQuery.next
end;
is where I populated the TObjectList.
ASKER
Thanks for that other info btw Russel, that was new to me so nice to learn.
ASKER
Where I create my Temp_CBRecord for populating my TObjectList, the only thing I can think about is that the reason it is displaying the same record is that I am over-writing previous records with the last one.
Am I using this incorrectly .. MyList.Add(Temp_CBRecord) .. and then deleting values when I go back round the loop again to create a new MyList.Add(Temp_CBRecord)
Am I using this incorrectly .. MyList.Add(Temp_CBRecord) .. and then deleting values when I go back round the loop again to create a new MyList.Add(Temp_CBRecord)
ASKER
Ok .. think Im definitely overwriting my TCBRecord everytime I populate my MyList .. I just assumed it would "add" the record to MyList and then let me create a new one over the top of it
ASKER
This is where the problem area is .. after a bit of debugging
Procedure TThisForm.Populate_MyList;
var
Temp_CBRecord: TCBRecord;
begin
Temp_CBRecord := TCBRecord.create;
//dmAcc is a datamodule holding my TIBQuery IBQ_Cashbook
with dmAcc, IBQ_Cashbook do
begin
//Loop and add records to a certain date
while (fieldbyname('ENTRY_DATE') .AsDateTim e < EndOfTheMonth(DTP_1Month.D ate)) and not eof do
begin
Temp_CBRecord.sCR_DR := FieldByName('CR_DR').AsStr ing;
Temp_CBRecord.sDesc := FieldByName('CR_DR_DESC'). AsString;
Temp_CBRecord.sReason := FieldByName('REASON').AsSt ring;
Temp_CBRecord.dAmount := FieldByName('AMOUNT').AsFl oat;
Temp_CBRecord.dCBDate := FieldByName('ENTRY_DATE'). AsDateTime ;
Temp_CBRecord.sOrderNo:= FieldByName('ORDER_NO').As String;
MyList.Add(Temp_CBRecord); //Overwriting previous records added to MyList every loop it seems.
next
end;
end
end;
Procedure TThisForm.Populate_MyList;
var
Temp_CBRecord: TCBRecord;
begin
Temp_CBRecord := TCBRecord.create;
//dmAcc is a datamodule holding my TIBQuery IBQ_Cashbook
with dmAcc, IBQ_Cashbook do
begin
//Loop and add records to a certain date
while (fieldbyname('ENTRY_DATE')
begin
Temp_CBRecord.sCR_DR := FieldByName('CR_DR').AsStr
Temp_CBRecord.sDesc := FieldByName('CR_DR_DESC').
Temp_CBRecord.sReason := FieldByName('REASON').AsSt
Temp_CBRecord.dAmount := FieldByName('AMOUNT').AsFl
Temp_CBRecord.dCBDate := FieldByName('ENTRY_DATE').
Temp_CBRecord.sOrderNo:= FieldByName('ORDER_NO').As
MyList.Add(Temp_CBRecord);
next
end;
end
end;
ASKER
I know Ive made an object just to hold data ...
Do you think maybe I would have been better just creating a record instead
Unless there is an easy solution Im not spotting in my n00bness
I presume I need a number of Temp_CBRecord 's .. but I dont know how many I will need :o/
Do you think maybe I would have been better just creating a record instead
Unless there is an easy solution Im not spotting in my n00bness
I presume I need a number of Temp_CBRecord 's .. but I dont know how many I will need :o/
You just needed to move the following line down:
Temp_CBRecord := TCBRecord.create;
Procedure TThisForm.Populate_MyList;
var
Temp_CBRecord: TCBRecord;
begin
//dmAcc is a datamodule holding my TIBQuery IBQ_Cashbook
with dmAcc, IBQ_Cashbook do
begin
//Loop and add records to a certain date
while (fieldbyname('ENTRY_DATE') .AsDateTim e < EndOfTheMonth(DTP_1Month.D ate)) and not eof do
begin
Temp_CBRecord := TCBRecord.create; //*************** create a record for each in table
Temp_CBRecord.sCR_DR := FieldByName('CR_DR').AsStr ing;\
Temp_CBRecord.sDesc := FieldByName('CR_DR_DESC'). AsString;
Temp_CBRecord.sReason := FieldByName('REASON').AsSt ring;
Temp_CBRecord.dAmount := FieldByName('AMOUNT').AsFl oat;
Temp_CBRecord.dCBDate := FieldByName('ENTRY_DATE'). AsDateTime ;
Temp_CBRecord.sOrderNo:= FieldByName('ORDER_NO').As String;
MyList.Add(Temp_CBRecord); //Overwriting previous records added to MyList every loop it seems.
next
end;
end
end;
Shane
Temp_CBRecord := TCBRecord.create;
Procedure TThisForm.Populate_MyList;
var
Temp_CBRecord: TCBRecord;
begin
//dmAcc is a datamodule holding my TIBQuery IBQ_Cashbook
with dmAcc, IBQ_Cashbook do
begin
//Loop and add records to a certain date
while (fieldbyname('ENTRY_DATE')
begin
Temp_CBRecord := TCBRecord.create; //*************** create a record for each in table
Temp_CBRecord.sCR_DR := FieldByName('CR_DR').AsStr
Temp_CBRecord.sDesc := FieldByName('CR_DR_DESC').
Temp_CBRecord.sReason := FieldByName('REASON').AsSt
Temp_CBRecord.dAmount := FieldByName('AMOUNT').AsFl
Temp_CBRecord.dCBDate := FieldByName('ENTRY_DATE').
Temp_CBRecord.sOrderNo:= FieldByName('ORDER_NO').As
MyList.Add(Temp_CBRecord);
next
end;
end
end;
Shane
ASKER
geez .. silly mistake.
thanks for all your help!
thanks for all your help!
Shane