Dificuldade com TList
Olá pessoal,
estou tentado fazer um exemplo conforme mostrado abaixo com o TList.
Defini uma classe a titulo de exemplo chamada TPessoa conforme o código abaixo:
Minha idéia e colocar uma lista de pessoas no TList :shock: . Até ai sem problemas defini uma variável do tipo TList chamada Lista e criei ela no evento OnCreate do Form. No OnDestroy do form libero ela.
Defini um procedimento para inserir pessoas na lista. Esse procedimento cria uma objeto do tipo TPessoa atribui valores a ele e inseri na lista como pode ser observado no código abaixo:
Minha primeira dúvida: :oops:
:arrow: P.Free;
Como foi definido uma variável do tipo TPessoa dentro da função InseriPessoaLista devo liberar ela ao finalizar o procediemento? Se fizer isso consigo ler os dados da pessoa ao percorrer a lista? :oops:
Feito esse procedimento criei um outro para ler as informações da lista conforme pode ser visto na listagem abaixo:
Esse procedimento é executado sem problemas quando o obejto TPessoa da função ´InseriPessoaLista´ não é liberado. Se ele é liberado ´P.Free´ ocorre erro ao executar o procedimento ´LeLista´.
Após isso definir um procedimento para retornar uma pessoa definida uma determinada chave. A minha idéia é passar o valor da chave e ter como retorno da função um objeto do tipo TPessoa.
Estou TENTANDO mas não estou conseguido:
EXISTE alguma forma mais [b:3129382b01]inteligente[/b:3129382b01] de localizar a pessoa na lista?
Por enquanto é isso....
estou tentado fazer um exemplo conforme mostrado abaixo com o TList.
Defini uma classe a titulo de exemplo chamada TPessoa conforme o código abaixo:
TPessoa = class public Chave : integer; Nome : string; Data : tDate; end;
Minha idéia e colocar uma lista de pessoas no TList :shock: . Até ai sem problemas defini uma variável do tipo TList chamada Lista e criei ela no evento OnCreate do Form. No OnDestroy do form libero ela.
Lista : TList; procedure TForm1.FormCreate(Sender: TObject); begin Lista := TList.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin Lista.Free; end;
Defini um procedimento para inserir pessoas na lista. Esse procedimento cria uma objeto do tipo TPessoa atribui valores a ele e inseri na lista como pode ser observado no código abaixo:
procedure TForm1.InseriPessoaLista(Chave : integer; Nome : string; DataNascimento : TDate); var P : TPessoa; begin P := TPessoa.Create; P.Nome := Nome; P.Data := DataNascimento P.Chave := Chave //Adicionando na lista Lista.Add(P); //DEVO OU NÃO DEVO LIBERAR O OBJETO P? // P.Free; end;
Minha primeira dúvida: :oops:
:arrow: P.Free;
Como foi definido uma variável do tipo TPessoa dentro da função InseriPessoaLista devo liberar ela ao finalizar o procediemento? Se fizer isso consigo ler os dados da pessoa ao percorrer a lista? :oops:
Feito esse procedimento criei um outro para ler as informações da lista conforme pode ser visto na listagem abaixo:
procedure TForm1.LeLista(); begin for i:=0 to Lista.Count-1 do begin ListaBox1.Items.Add(FormatFloat(´00´, TPessoa(Lista.Items[i]).Chave+´ - ´+TPessoa(Lista.Items[i]).Nome + ´ - ´ +FormatDateTime(´dd/mm/yyyy´, TPessoa(Lista.Items[i]).Data); end; end;
Esse procedimento é executado sem problemas quando o obejto TPessoa da função ´InseriPessoaLista´ não é liberado. Se ele é liberado ´P.Free´ ocorre erro ao executar o procedimento ´LeLista´.
Após isso definir um procedimento para retornar uma pessoa definida uma determinada chave. A minha idéia é passar o valor da chave e ter como retorno da função um objeto do tipo TPessoa.
Estou TENTANDO mas não estou conseguido:
function TForm1.RetornaPessoa(chave : integer) : TPessoa var i : integer; begin Result := nil; for i:=0 to Lista.Count-1 do begin if TPessoa(Lista.Items[i]).Chave = Chave then begin result := TPessoa(Lista.Items[i])); break; end; end; end;
EXISTE alguma forma mais [b:3129382b01]inteligente[/b:3129382b01] de localizar a pessoa na lista?
Por enquanto é isso....
Carlosib
Curtidas 0
Respostas
Carlosib
14/09/2007
Sobe :oops:
GOSTEI 0
Jessedelsole
14/09/2007
Olá carlos
A classe TList, guarda apenas uma referência de algum objeto. A referência seria um ponteiro de memória, apenas um número inteiro. Ou seja, se você liberar o objeto pessoa, depois a lista não vai mais conseguir encontrá-la.
Quanto a maneira que você utilizou para localizar o cliente pelo código, achei q ficou legal. Porém, outra maneira de se fazer isso seria criar um array dinâmico de TPessoa, que dispensaria o uso da lista, deixando teoricamente o programa mais leve :
Quando vou inserir um cliente, vou redimensionando o array conforme a demanda :
Aqui é a função para retornar a [b:10bb86cf45]referência[/b:10bb86cf45] do cliente requisitado.
caso queira retornar um novo objeto de pessoa para o cliente requisitado, a função ficaria assim :
Aqui irei adicionar as pessoas num listBox
Por último estou liberando todos as pessoas instanciadas :
Espero ter ajudado em alguma coisa
A classe TList, guarda apenas uma referência de algum objeto. A referência seria um ponteiro de memória, apenas um número inteiro. Ou seja, se você liberar o objeto pessoa, depois a lista não vai mais conseguir encontrá-la.
Quanto a maneira que você utilizou para localizar o cliente pelo código, achei q ficou legal. Porém, outra maneira de se fazer isso seria criar um array dinâmico de TPessoa, que dispensaria o uso da lista, deixando teoricamente o programa mais leve :
//variavel global Pessoas : array of TPessoa
Quando vou inserir um cliente, vou redimensionando o array conforme a demanda :
procedure TForm1.insereCliente(nome: string; chave: integer); begin SetLength(Pessoas,high(Pessoas)+2); Pessoas[high(Pessoas)] := TPessoa.Create; Pessoas[high(Pessoas)].Nome := nome; Pessoas[high(Pessoas)].chave := chave; end;
Aqui é a função para retornar a [b:10bb86cf45]referência[/b:10bb86cf45] do cliente requisitado.
function TForm1.RetornaPessoa(chave: integer): Tpessoa; var i:integer; begin result := nil; for i := low(Pessoas) to high(Pessoas) do if Pessoas[i].chave = chave then begin result := Pessoas[i]; break; end; end;
caso queira retornar um novo objeto de pessoa para o cliente requisitado, a função ficaria assim :
function TForm1.retornaObjetoDePessoa(chave: integer): TPessoa; var i : integer; begin result := nil; for i := low(Pessoas) to high(Pessoas) do if Pessoas[i].chave = chave then begin result := TPessoa.Create; result.Nome := pessoas[i].Nome; result.chave := pessoas[i].chave; break; end; end;
Aqui irei adicionar as pessoas num listBox
procedure TForm1.Button1Click(Sender: TObject); var i : integer; begin for i := Low(Pessoas) to high(Pessoas) do listbox1.Items.Add(Pessoas[i].Nome); end;
Por último estou liberando todos as pessoas instanciadas :
procedure TForm1.FormDestroy(Sender: TObject); var i : integer; begin for i := high(pessoas) downto low(Pessoas) do FreeAndNil(Pessoas[i]); end;
Espero ter ajudado em alguma coisa
GOSTEI 0
Carlosib
14/09/2007
Olá amigo,
obrigado pela resposta.
1) Já uso array dinâmico. Porém achava que com TList ou outro ´derivado´ teria mais ´facilidades´.
2) porque você usa FreeAndNil(Pessoas[i]) ao invés de Pessoas[i].Free?
Qual seria a diferença entre eles?
obrigado pela resposta.
1) Já uso array dinâmico. Porém achava que com TList ou outro ´derivado´ teria mais ´facilidades´.
2) porque você usa FreeAndNil(Pessoas[i]) ao invés de Pessoas[i].Free?
Qual seria a diferença entre eles?
GOSTEI 0
Rinez
14/09/2007
Prezado colega:
Voce pode usar clientedataset da paleta Data Acess
Um exemplo para voce testar, quando a perform eu não sei,
outros colegas poderão dar opinião.
As vezes uso no dropdown do combobox para carregar nome de arquivo texto em ordem decrescente:
Coloque em um form um clientedataset, 3 edits, um listbox e e botoes.
coloque o nome do clientdataset cdspessoas
Teste aí e nos responda o que achou.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, DB, DBClient;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
cdspessoas: TClientDataSet;
ListBox1: TListBox;
BitBtn3: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IF Cdspessoas.FieldCount=0 THEN BEGIN
with Cdspessoas do begin
with FieldDefs.AddFieldDef do
begin
DataType := ftInteger;
Name := ´Chave´;
end;
with FieldDefs.AddFieldDef do
begin
DataType := ftSTRING;
size:=400;
Name := ´PESSOA´;
end;
with FieldDefs.AddFieldDef do
begin
DataType := ftdate;
Name := ´DATA´;
end;
CreateDataSet;
end; //with cdpessoas do begin
end; //IF Cdpessoas.FieldCount=0 THEN BEGIN
CDSPESSOAS.EmptyDataSet; // limpacdsteste
showmessage(´ClientDataset Criado com sucesso´);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
cdspessoas.Close;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
i:integer;
mdata:tdate;
begin
try
i:=strtoint(edit1.Text);
except
on e: exception do begin
// on EConvertError do begin
showmessage(´erro número invádo´);
edit1.setfocus;
exit;
end; end;
try
mdata:=strtodate(edit3.Text);
except
on e: exception do begin
showmessage(´erro data inváda´);
edit3.setfocus;
exit;
end; end;
CDSPESSOAS.OPEN;
cdspessoas.Append;
cdspessoas.fieldbyname(´chave´).asinteger:=I;
cdspessoas.fieldbyname(´pessoa´).asstring:=EDIT2.TEXT;
cdspessoas.fieldbyname(´data´).value:=STRTODATE(EDIT3.Text);
CDSPESSOAS.Post;
LISTBOX1.Items.Add(cdspessoas.fieldbyname(´chave´).ASSTRING+´ - ´+cdspessoas.fieldbyname(´pessoa´).asstring+´ - ´+
cdspessoas.fieldbyname(´data´).ASSTRING);
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
var
s:string;
begin
s:= InputBox(s, ´Entre com Numero a procurar´, ´´);
cdspessoaS.filtered := False;
cdspessoaS.filter := ´CHAVE = ´ + QuotedStr(S);
cdspessoas.Filtered := True;
SHOWMESSAGE(´CHAVE ´+CDSPESSOAS.FIELDBYNAME(´CHAVE´).AsString+
´Nome ´+CDSPESSOAS.FIELDBYNAME(´pessoa´).AsString);
end;
end.
Voce pode usar clientedataset da paleta Data Acess
Um exemplo para voce testar, quando a perform eu não sei,
outros colegas poderão dar opinião.
As vezes uso no dropdown do combobox para carregar nome de arquivo texto em ordem decrescente:
Coloque em um form um clientedataset, 3 edits, um listbox e e botoes.
coloque o nome do clientdataset cdspessoas
Teste aí e nos responda o que achou.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, DB, DBClient;
type
TForm1 = class(TForm)
Edit1: TEdit;
Edit2: TEdit;
Edit3: TEdit;
BitBtn1: TBitBtn;
BitBtn2: TBitBtn;
cdspessoas: TClientDataSet;
ListBox1: TListBox;
BitBtn3: TBitBtn;
procedure BitBtn1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure BitBtn2Click(Sender: TObject);
procedure BitBtn3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IF Cdspessoas.FieldCount=0 THEN BEGIN
with Cdspessoas do begin
with FieldDefs.AddFieldDef do
begin
DataType := ftInteger;
Name := ´Chave´;
end;
with FieldDefs.AddFieldDef do
begin
DataType := ftSTRING;
size:=400;
Name := ´PESSOA´;
end;
with FieldDefs.AddFieldDef do
begin
DataType := ftdate;
Name := ´DATA´;
end;
CreateDataSet;
end; //with cdpessoas do begin
end; //IF Cdpessoas.FieldCount=0 THEN BEGIN
CDSPESSOAS.EmptyDataSet; // limpacdsteste
showmessage(´ClientDataset Criado com sucesso´);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
cdspessoas.Close;
end;
procedure TForm1.BitBtn2Click(Sender: TObject);
var
i:integer;
mdata:tdate;
begin
try
i:=strtoint(edit1.Text);
except
on e: exception do begin
// on EConvertError do begin
showmessage(´erro número invádo´);
edit1.setfocus;
exit;
end; end;
try
mdata:=strtodate(edit3.Text);
except
on e: exception do begin
showmessage(´erro data inváda´);
edit3.setfocus;
exit;
end; end;
CDSPESSOAS.OPEN;
cdspessoas.Append;
cdspessoas.fieldbyname(´chave´).asinteger:=I;
cdspessoas.fieldbyname(´pessoa´).asstring:=EDIT2.TEXT;
cdspessoas.fieldbyname(´data´).value:=STRTODATE(EDIT3.Text);
CDSPESSOAS.Post;
LISTBOX1.Items.Add(cdspessoas.fieldbyname(´chave´).ASSTRING+´ - ´+cdspessoas.fieldbyname(´pessoa´).asstring+´ - ´+
cdspessoas.fieldbyname(´data´).ASSTRING);
end;
procedure TForm1.BitBtn3Click(Sender: TObject);
var
s:string;
begin
s:= InputBox(s, ´Entre com Numero a procurar´, ´´);
cdspessoaS.filtered := False;
cdspessoaS.filter := ´CHAVE = ´ + QuotedStr(S);
cdspessoas.Filtered := True;
SHOWMESSAGE(´CHAVE ´+CDSPESSOAS.FIELDBYNAME(´CHAVE´).AsString+
´Nome ´+CDSPESSOAS.FIELDBYNAME(´pessoa´).AsString);
end;
end.
GOSTEI 0
Jessedelsole
14/09/2007
Free libera o objeto da memória,
enquanto freeAndNil, além de liberar o objeto da memória, remove também o ponteiro do mesmo .
enquanto freeAndNil, além de liberar o objeto da memória, remove também o ponteiro do mesmo .
GOSTEI 0