Fórum Dificuldade com TList #346016
14/09/2007
0
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
Curtir tópico
+ 0Posts
16/09/2007
Carlosib
Gostei + 0
17/09/2007
Jessedelsole
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
17/09/2007
Carlosib
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
17/09/2007
Rinez
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
19/09/2007
Jessedelsole
enquanto freeAndNil, além de liberar o objeto da memória, remove também o ponteiro do mesmo .
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)