Pular para o conteúdo principal

Free Pascal - Usando TList

A classe TList é usada para gerenciar uma coleção de ponteiros, com a grande vantagem de ser dinâmica. Ela dispõe de métodos para fazer busca na lista e ordenar os elementos, entre outros. No exemplo abaixo fazemos uso de alguns desses métodos.


unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TContato = class
    private
      NomeContato     : String;
      TelefoneContato : String;

    public
      property Nome : String
          read NomeContato;
      property Telefone : String
          read TelefoneContato;

      constructor Create(const pNomeContato       : String;
                         const pTelefoneContato   : String);
  end;

  { TfrmTlist }

  TfrmTlist = class(TForm)
    Button1: TButton;
    ListBox1: TListBox;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
    Agenda : TList;

    procedure MostraAgenda;
  public
    { public declarations }
  end;

var
  frmTlist: TfrmTlist;

implementation

{$R *.lfm}

constructor TContato.Create(const pNomeContato      : String;
                             const pTelefoneContato : String);
begin
  self.NomeContato     := pNomeContato;
  self.TelefoneContato := pTelefoneContato;
end;

function comparaPorNome(Item1 : Pointer; Item2 : Pointer) : Integer;
var
  contato1, contato2 : TContato;
begin
  contato1 := TContato(Item1);
  contato2 := TContato(Item2);

  if      contato1.Nome > contato2.Nome
  then Result := 1
  else if contato1.Nome = contato2.Nome
  then Result := 0
  else Result := -1;
end;

procedure TfrmTlist.Button1Click(Sender: TObject);
var
  contato : TContato;

begin
  Agenda := TList.Create;

  contato := TContato.Create('Nádia Alves', '3523-0001');
  Agenda.Add(contato);
  contato := TContato.Create('Célio Silva', '3524-0000');
  Agenda.Add(contato);

  Agenda.Add(TContato.Create('Hélio Costa', '3320-1000'));
  Agenda.Add(TContato.Create('Aldo Sousa', '3321-0001'));

  MostraAgenda;
  ShowMessage('Ordenando pelo nome. Pressione OK');
  Agenda.Sort(@comparaPorNome);

  MostraAgenda;
  ShowMessage('Inserindo novo contato. Pressione OK');
  Agenda.Insert(2, TContato.Create('Luis Gonzaga', '3325-4000'));
  MostraAgenda;
  ShowMessage('Excluindo um contato. Pressione OK');
  Agenda.Delete(4);
  ShowMessage('Pressione OK');
  Agenda.free;
end;

procedure TfrmTlist.MostraAgenda;
var
  i : Integer;
begin
  ListBox1.Items.Clear;
  for i := 0 to Agenda.Count-1 do
  begin
    ListBox1.Items.Add(TContato(Agenda[i]).Nome+' - '+
                      (TContato(Agenda[i]).Telefone));
  end;
end;

end.


No exemplo criamos uma classe Contato que será usada para povoar um TList que denominamos Agenda. Um TListBox é usado para apresentar os dados do TList.
Nas linhas que vão de 74 a 95 é onde acontece tudo que pretendemos mostrar. Inicialmente o TList é criado. Em seguida, são criados vários objetos Contato, que são adicionados à Agenda utilizando o método Add(). Este método sempre adiciona um objeto no fim da lista.
Após isso chamamos o método MostraAgenda, que foi criado para visualizar os dados da Agenda no TListBox. Na linha 86 há uma chamada ao método Sort(), que recebe como argumento o método comparaPorNome(). Aqui cabe uma explicação mais detalhada.
A ordenação de uma lista de objetos não é uma coisa tão natural como ordenar números inteiros ou strings. Como sabemos um objeto tem vários campos e por isso precisamos definir qual o critério que será usado para decidir que um objeto A é maior, menor ou igual a um outro objeto B. Por este motivo o método Sort() deve receber como parâmetro uma variável procedural, ou seja, um método que estabelece o critério de ordenação.
Dessa forma, foi criado o método comparaPorNome(), que recebe os ponteiros dos dois objetos a serem comparados. Tal método deve retornar -1 se o primeiro objeto for menor que o segundo, 1 se for maior e 0 se forem iguais. No nosso exemplo definimos que dois Contatos são iguais quando tem nomes iguais. Leia mais sobre variáveis procedurais no post Free Pascal - Variáveis Procedurais. Deve-se ressaltar que o Free Pascal define apenas como deve ser a assinatura do método que ele espera receber em Sort(). A implementação cabe ao desenvolvedor.
Na linha 90 um novo objeto é inserido na posição 2 do TList. Note que a primeira posição é 0.
Usamos o método Delete() para deletar um objeto em uma determinada posição. Na linha 93 excluímos o objeto da posição 4.
Quando a TList não é mais necessária, liberamos a memória usada chamando Free. Para criar uma lista de strings prefira usar TStrings ou sua descendente TStringList.

Comentários

José Roberto disse…
ótimo conteúdo o seu blog prof. Carlos muito obrigada por dividir o seu conhecimento com todos nós, o seu blog já me ajudou muito em meus projetos só tenho a agradecer ao senhor !
Anônimo disse…
Estou usando o Lazarus -- eu Criei um pequeno programa, forneça dois valores e mostra a soma desses dois valores. Quando salvo o a minha aplicação como arquivo.exe ele não roda no windows 7. O que devo fazer? mauricio.s.trindade@hotmail.com - desde já agradeço!
Professor Carlos disse…
Você criou uma aplicação console ou com interface gráfica. Você salvou o projeto com a extensão .exe ou compilou o código? Não está muito claro pra mim o que você fez,
Adriane disse…
Olá professor Carlos ... seu blog está sendo muito útil para preparar minhas aulas para o curso de Análise de Desenvolvimento de Sistemas - Fatec/Mogi das Cruzes/SP. Obrigada por disponibilizar tanto conteúdo interessante para a aprendizagem ... Mudando de assunto estou querendo usar o Sender para verificar qual componente ativou determinado evento, mas o Lazarus não reconhece o 'sender' ???? aguardo ... e de qualquer forma obrigada ...
Professor Carlos disse…
Que bom que esta ajudando. Quanto ao Sender, tente referenciar o components assim, como neste exemplo: TButton(Sender)^.Caption
konlinuxguara disse…
Parabéns!

Sou usuário do GNU/Pascal, não conheço muito, porém a minha aprendizagem é crescente.
Sistema como calculadora, agenda, entre outros já consigo programar e usar, agora estou buscando um material que me auxilie a usar essa linguagem como se usa o PHP, em páginas para inserir dados e recuperá-los, pois usando o SGDB Postgresql faço todo desenvolvimento com PHP e HTML, e gostaria de implementar o conhecimento, como Gnu/Pascal.
Tudo faço no Slackware.
Grato.
http://konlinux.com
Anônimo disse…
Ex-aluna....:)
Professor Carlos estou querendo tirar uma dúvida, para instalar o firebird sendo que meu propósito é para o desenvolvimento de aplicações, como devo instalar? É como serviço ou aplicação? E
Professor Carlos disse…
Oi ex-aluna :)

De qualquer maneira uma aplicação se conectará ao banco de dados. Mas, se você instalar como aplicação cuide para que o servidor rode automaticamente na inicialização do sistema operacional. Isso dá pra configurar durante a instalação.

Postagens mais visitadas deste blog

Lazarus - Acessando banco de dados com SQLdb - Parte I

Para fazer nossa primeira aplicação usando banco de dados no Lazarus vamos usar o SQLite e o conjunto de componentes nativo SQLdb. Inicialmente vamos apresentar passo como essa aplicação foi criada. Essa foi a maneira que eu fiz, e eu agradeço sugestões e questionamentos que pessoas que já passaram por essa experiência. Depois irei fazer algumas considerações sobre o uso do SQLdb. SQLite SQLite é uma biblioteca que implementa um motor de banco de dados SQL. É livre para qualquer finalidade, seja uso particular ou comercial. Lê e escreve em um único arquivo que pode ter além de tabelas, índices, gatilhos e visões. Executa em várias plataformas e é indicado para aplicações embarcadas. Maiores detalhes podem ser encontrados no site oficial. Para usá-lo, baixe-o do site e faça a instalação adequada para o seu sistema operacional. No Windows isso é muito simples, apenas copie sqlite3.dll para o system32 da pasta do sistema operacional. Existe uma ferramenta de linha de comando chamada

Tipos de dados no SQLite

Em SQLite, diferente de outros motores de banco de dados, o tipo de dado de um valor está associado com o valor propriamente dito, e não com o seu contêiner. É um sistema de tipo dinâmico. Um campo de uma tabela em SQLite pode receber qualquer tipo de dado. Assim, o SQLite simplesmente ignora o tipo informado no comando CREATE TABLE. Então, dizemos que no SQLite existem classes de armazenamento. E essas classes são: NULL - como em qualquer outro banco de dados. INTEGER - inteiro com sinal, armazenado em 1, 2, 3, 4, 6 ou 8 bytes dependendo da grandeza do valor. REAL - valor de ponto flutuante armazenado em 8 bytes. TEXT - uma string armazenada usando UTF-8, UTF-16BE ou UTF-16LE. BLOB - armazena um blob, como indica o nome. Uma coluna INTEGER PRIMARY é uma exceção. Só aceita números inteiros. Qualquer valor em um comando SQL tem uma classe de armazenamento implícita. Durante a execução do comando SQL, o SQLite pode converter valores entre classes numéricas (INTEGER e REAL)

Lazarus - Criando relatórios com FortesReport (Parte I)

Para a criação de relatórios, o Lazarus já trás o componente LazReport, no entanto ele precisa ser instalado no IDE. Para fazer a instalação do pacote, acesse o menu Package -> Open package file (.lpk) . Localize o diretório de instalação do Lazarus e na pasta components abra lazreport e depois source . Abra o pacote lazreport.lpk , clique em Compile e depois em Install . Como já sabemos isso irá recompilar o IDE. Depois de inicializado novamente estará disponível a aba LazReport . Leia aqui um tutorial básico sobre o LazReport. No entanto queremos mostrar uma alternativa ao LazReport . Por essa razão, vamos apresentar neste artigo o FortesReport . Para quem conhece o QuickReport, que fazia parte do Delphi, não terá dificuldade de desenvolver com esse componente. Baixe o pacote aqui e instale. Os procedimentos são semelhantes aos que mostramos acima. Você terá uma nova aba chamada Fortes Report . Conectando o banco de dados O primeiro passo para criar a aplicação é fazer