1
votes

Say i have a class called TMachine I currently create 1 class like so

 Machine := MachineShape.TMachine.create(self);

but I need more then 1, never really sure how many i need as it depends on # of machines in the database at the time, Should never be over 20. So I know i need an array of some type in the var section. Currently i have

procedure TFLayout1.GetClick(Sender: TObject);
var
  machine : TMachine;
begin
 .....

  //gets number of machines in total
  while not fdeptlayout.ADOQuery1.Eof do
    begin
      fdb.count := fdb.count+1;
      fdeptlayout.ADOQuery1.Next;
    end;

  //restarts back at first query
  fdeptlayout.ADOQuery1.First;


  //creates the shape
  while not fdeptlayout.ADOQuery1.Eof do
    begin
        machine := MachineShape.TMachine.Create(self);
        machine.PlaceShape(44,44,'CM402','first','123/33/123');
        fdeptlayout.ADOQuery1.Next;
    end;
end;

currently that will place 1 machine on the form "Machine" . I Need it to place "Machine1" "Machine2" ... for how ever many are in the query. Thus "machine" needs replaced by an array some how? everything is created at runtime.

2

2 Answers

5
votes

The simplest is to use a list. Use a generic list from Generics.Collections.

FList: TList<TMachine>;

For you needs, you would declare the list to be a field in one of your classes. The class that you want to control and manage all the machines.

Create it like this:

FList := TList<TMachine>.Create;

Add new members to the list like this:

FList.Add(Machine);

Iterate over the list like this:

for Machine in FList do
  Machine.DoSomething;

If you would like the list to control the lifetime of the machines, then use TObjectList<T> instead.

FList: TList<TMachine>;
....
FList := TObjectList<TMachine>.Create;

Then when you remove items from the list, clear the list, destroy the list etc., the machines will also be destroyed.

The Delphi documentation contains an example illustrating the use of TObjectList<T>.


So, to make it clear, your while loop would look like this:

while not fdeptlayout.ADOQuery1.Eof do
begin
  machine := MachineShape.TMachine.Create(self);
  FList.Add(machine);
  machine.PlaceShape(44,44,'CM402','first','123/33/123');
  fdeptlayout.ADOQuery1.Next;
end;

Then at some other point in your code when you need to iterate over all machines, use the code in the for loop above.


Of course, this may all be a complete red herring. Perhaps you don't ever need to refer to your machine objects outside the routine in the question. In which case you don't need a list at all, and the code in the question is already perfectly adequate.

I note that you state:

Currently that will place one machine on the form.

That is not so. The while loop will create one machine object for each iteration of your while loop. The fact that you re-use the local variable machine doesn't change that. Each time round the loop you call TMachine.Create and so create a new instance each iteration.

2
votes

You can place the machines in a TObjectList

In your class definition add

FMachines: TObjectList<TMachine>;

Then in your FormCreate:

FMachines:= TObjectList<TMachine>.Create;

and in FormDestroy:

FMachines.Free;

In your GetClick method dd the created machine to the list like so:

machine := MachineShape.TMachine.Create(self);
FMachines.Add(machine);

You can then refer to the created machines by accessing the FMachines list.