Criar objetos dentro de um for

Delphi

24/03/2009

Pessoal me deparei com algo que nunca prescisei fazer antes:

Criar objetos dentro de um for (laço), como não sei quantos objetos vou criar uso sempre o p :TPanelAlerta;

abaixo o trecho que contem o laço:

var
  p     :TPanelAlerta;
begin  
   while not CDS.Eof do
   begin 
       P :=TPanelAlerta.Create(pnl);
       P.SetCliente(CDS.FieldByName(´ID_CLIENTE´).AsInteger, CDS.FieldByName(´DC_CLIENTE´).AsString);

       P.CriaEstrutura;
       CDS.Next;
    end;



Abaixo o método do meu objeto

procedure TPanelAlerta.SetCliente(ID: integer; DC: String);
begin
  self.FIdCliente :=ID;
  Self.FDcCliente :=DC;
end;

O que está acontecendo é o seguinte como no for sempre uso o  p     :TPanelAlerta ele está sobreescrevendo o valor de self.FIdCliente , ou seja depois de criados todos os objetos, todos os objetos tem o mesmo valor para self.FIdCliente, sendo que na atribuição os valores são diferentes.




Diegotiemann

Diegotiemann

Curtidas 0

Respostas

Diegotiemann

Diegotiemann

24/03/2009

OBS: TPanelAlerta é um objeto que eu criei.


GOSTEI 0
Woinch

Woinch

24/03/2009

Você precisará de um vetor ou array.

var 
  p     : array of TPanelAlerta; 
  i      : Integer;

begin  
   i := 0;

   while not CDS.Eof do 
   begin 
       SetLength(p, i +1); //aumenta o tamanho do array
       P[i] :=TPanelAlerta.Create(pnl); //cria o objeto no indice I do array
       P[i].SetCliente(CDS.FieldByName(´ID_CLIENTE´).AsInteger, CDS.FieldByName(´DC_CLIENTE´).AsString); 

       P[i].CriaEstrutura; 
       CDS.Next;
       i++; 
    end;


Para retornar um determinado objeto dentro desse array basta utilizar p[NUMERO DE ZERO ATÉ O TAMANHO -1]. Exemplos:

ShowMessage(IntToStr(p[0].GetCliente)); //retorna o cliente (se seu objeto possuir esse método) do primeiro objeto criado.
ShowMessage(IntToStr(p[0].GetCliente)); //retorna o cliente (se seu objeto possuir esse método) do segundo objeto criado.
...
ShowMessage(IntToStr(p[n].GetCliente)); //retorna o cliente (se seu objeto possuir esse método) do n-ézimo objeto criado.


Para uma alternativa mais profissional, leia um pouco sobre estrutura de dados. O delphi possui uma unit chamada Contnrs, dentro existe uma classe TObjectList. Com essa classe é possível adicionar, remover, procurar objetos de uma lista de forma dinâmica.


Espero ter ajudado.


GOSTEI 0
Javapaulomg

Javapaulomg

24/03/2009

Amigo pelo oque pude entender do seu exemplo você quer uma forma de gerenciar as instâncias dos objetos que está criando, porem da forma que está fazendo a variável de referencia e sempre sobreescrita pela ultima instância criada.
Para o seu caso em especifico como o número de objetos e variável, lhe sugiro utilizar um objeto fora do for para controlar essas instâncias.
O ´TObjectList´ da unit ´Contnrs´, ira lhe auxilixar, basta criar uma instancia dele e adicionar seus objetos, e posteriormente ao destruir o mesmo ele ira destruir as instâncias contidas nele tambem, caso tenha sido inicializado como ´True´ em seu contrutor.
Caso tenha entendido errado so postar ai que olhamos. Inte+.


GOSTEI 0
Javapaulomg

Javapaulomg

24/03/2009


var
   p                : TPanelAlerta;
   listaObjetos : TObjectList;
begin

   listaObjetos := TObjectList.Create(True);

   while not CDS.Eof do
   begin

       p := TPanelAlerta.Create(pnl); 

       p.CriaEstrutura;

       listaObjetos.add(p);

       CDS.Next;

    end;

   FreeAndNil(listaObjetos);

end;




GOSTEI 0
Diegotiemann

Diegotiemann

24/03/2009

Vou testar as duas maneiras dai dou o retorno.


GOSTEI 0
Diegotiemann

Diegotiemann

24/03/2009

Até o momento testei só a 1ª maneira (array);

Dai aconteceu algo mais estranho ainda,
para testar criei um evento ao clique do mouse no objeto

  showMessage(intToStr(self.FidPavimento));


funcionou perfeitamente cada objeto mostrava seu valor

mas quanto tento acessar o valor de fora através do GetIdPaviemento, o único valor que reorna certo é o do último objeto, os outros retornaram valores aleatórios.


GOSTEI 0
Woinch

Woinch

24/03/2009

Como você está chamando essa função GetIdPavimento?


GOSTEI 0
Diegotiemann

Diegotiemann

24/03/2009

 while not CDS.Eof do
   begin
      SetLength(p, i +1); //aumenta o tamanho do array
     if CDS.RecNo mod 2 =0 then
        pnl :=pnl1
      else
        pnl :=pnl2;

       P[I] :=TPanelAlerta.Create(pnl);
       P[I].SetCliente(CDS.FieldByName(´ID_CLIENTE´).AsInteger, CDS.FieldByName(´DC_CLIENTE´).AsString);
       P[I].SetObra(CDS.FieldByName(´ID_OBRA´).AsInteger, CDS.FieldByName(´DC_OBRA´).AsString);
       P[I].SetPavimento(CDS.FieldByName(´ID_PAVIMENTO´).AsInteger, CDS.FieldByName(´DC_PAVIMENTO´).AsString);
       p[I].SetPrevisaoTermino(CDS.FieldByName(´PREVISAO_ENTREGA´).AsDateTime);
       p[I].SetPopUps(popProducao, popCerramica, popEPS, popFerragem, popConcretagem, popProj);
       P[I].CriaEstrutura;
       CDS.Next;
    end;

//aqui estou chamando a função pra testar
    for I := 0 to CDS.RecordCount - 1 do
      ShowMessage(´Pavimento: ´+IntToStr(p[i].GetIdPavimento)); 


Alguns dos métodos do objeto:

procedure TPanelAlerta.SetPavimento(ID: integer; DC: String);
begin
  Self.FIdPavimento :=ID;
  Self.FDcPavimento :=DC;
end;


function TPanelAlerta.GetIdPavimento: Integer;
begin
  result :=self.FIdPavimento;
end;


//quando adiciono esse métono a algum evento Ex: clique do mouse, dai ele exibe o valor certo
procedure TPanelAlerta.teste(sender: Tobject);
begin
  ShowMessage(´Id Pavimento:´+IntToStr(FIdPavimento));
end;








GOSTEI 0
Diegotiemann

Diegotiemann

24/03/2009

Com o TObjectList funcionou perfeitamente.

Obrigado


GOSTEI 0
POSTAR