Olá pessoal, notei que existem muitas dúvidas postadas nos fóruns sobre como gravar imagens em uma determinada base de dados e depois exibi-las na aplicação, principalmente sobre qual seria a melhor prática para esse tipo de desenvolvimento. Podemos desenvolver de 2 maneiras: a primeira seria criando um campo do tipo Blob na tabela desejada e dentro da aplicação seria codificado para gravar a imagem nesse campo, pessoalmente não gosto muito dessa técnica pois imaginem um cadastro de peças contendo 1000 imagens uma para cada peça, essa base de dados ficaria enorme e com isso poderíamos perder performance tanto da aplicação quanto do servidor. A segunda maneira seria criar um campo do tipo VARCHAR na tabela desejada e dentro da aplicação gravar no banco somente o caminho para imagem, eu sei que muitos podem questionar a questão de se trabalhar em rede, poderia ser difícil capturar as imagens em estações diferentes, nesse caso o mais sensato seria gravar essas imagens em uma pasta no servidor da rede, desse modo quando fosse necessário tanto gravação ou exibição da imagem a aplicação iria consultar somente uma pasta contendo todas as imagens no servidor.
Nesse artigo vou demonstrar a segunda maneira que é gravando somente o caminho para imagem no banco e posteriormente vamos navegar entre os registros e exibir novamente as imagens na tela, bem chega da conversa vamos codificar...
Para esse artigo criei uma base de dados utilizando o Firebird 2.5 + IBExpert com o nome de DEVMEDIA, e também uma tabela Imagens. Na listagem 1 exibe o script de criação da tabela.
Listagem 1: Script da Tabela Imagens
CREATE TABLE IMAGEM (
ID INTEGER NOT NULL,
TITULO_IMAGEM VARCHAR(40) CHARACTER SET WIN1252 COLLATE WIN1252,
CAMINHO_IMAGEM VARCHAR(500) CHARACTER SET WIN1252 COLLATE WIN1252);
ALTER TABLE IMAGEM ADD CONSTRAINT PK_IMAGEM PRIMARY KEY (ID);
Agora vamos criar um novo projeto no Delphi, e arrastar para o form alguns componentes, abaixo segue uma breve descrição sobre as configurações necessárias:
1 - TLabel
- Caption = “Descrição da Imagem:”
1 - TEdit
- Name = edtDescricao
- CharCase = ecUpperCase
1 - TImage
- Name = imgImagem
- Strech = true
1 - TDBGrid
- Align = AlBotton
- Name = grdImagem
- ReadOnly = true
- Options > dgEditing = false, dgRowSelect = true
4 - TBitBtn
1 - Name = btnCarregar
- Caption = “Carregar Imagem”
- Cursor = crHandPoint
- Hint = “Carregar Imagem”
- ShowHint = true
2 - Name = btnIncluirImagem
- Caption = “Gravar Imagem”
- Cursor = crHandPoint
- Hint = “Incluir imagem no banco de dados”
- ShowHint = true
3 - Name = btnAlteraImagem
- Caption = “Alterar Imagem”
- Cursor = crHandPoint
- Hint = “Alterar imagem gravada”
- ShowHint = true
4 - Name = btnExcluirImagem
- Caption = “Excluir Imagem”
- Cursor = crHandPoint
- Hint = “Excluir Imagem”
- ShowHint = true
Os componentes foram organizados como mostra a imagem abaixo:
Figura 1: Exibe layout final da tela
Os componentes para acesso ao banco de dados e o TOpenDialog para informar o caminho da imagem a ser gravada foram criados em RunTime, desse modo o código ficou um pouco extenso. Como a finalidade deste artigo é apenas demonstrar como podemos gravar o caminho e visualizar imagens através do das informações gravadas no banco de dados então não pretendo estender a explicação de criação de componentes em tempo de execução.
Gravar o caminho da imagem: primeiro temos que capturar seu caminho e para isso vamos usar um TOpenDialog, depois informamos uma descrição para imagem no edtDescricao e pressionamos o botão “Incluir Imagem”.
Alterar um caminho: temos que primeiro selecionar o registro no DBGrid depois pressionar o botão “Carregar Imagem” e selecionar qual será a nova imagem a ser capturado o caminho e depois pressionar o botão “Alterar Imagem”.
Excluir caminho: e bem simples, seleciona o registro no DBGrid e pressiona o botão “Excluir Imagem”.
Abaixo seguem várias listagens com os devidos códigos para o processamento das informações:
Listagem 2: Procedimento para conectar-se ao banco de dados
procedure TForm2.Conectar;
begin
//Procedimento para conectar-se ao banco de dados
Conexao := TSQLConnection.Create(nil);
try
//Passa os parâmetros para o objeto Conexao
Conexao.Connected := false;
Conexao.LoginPrompt := false;
Conexao.Params.Clear;
Conexao.ParamsLoaded := True;
Conexao.DriverName := 'Firebird';
Conexao.GetDriverFunc := 'getSQLDriverINTERBASE';
Conexao.LibraryName := 'dbxfb.dll';
Conexao.VendorLib := 'fbclient.dll';
Conexao.Params.Add('drivername=Firebird');
Conexao.Params.Add('hostname=LOCALHOST');
Conexao.Params.Add('user_name=SYSDBA');
Conexao.Params.Add('password=masterkey');
Conexao.Params.Add('port=3050');
Conexao.Params.Add('Database=C:\Projeto Imagens\DEVMEDIA.fdb');
Conexao.Connected := true;
Except
on E:Exception do
ShowMessage('Erro ao acessar banco de dados!'#13#10 + E.Message);
end;
end;
Listagem 3: Código do evento OnCreate do Form
procedure TForm2.FormCreate(Sender: TObject);
begin
//Inicia uma conexão com o banco de dados
Conectar();
//Carrega as informações no DDGrid
CarregaGrid();
end;
Listagem 4: Código do evento OnClick do botão btnCarregarImagem
procedure TForm2.btnCarregaImagemClick(Sender: TObject);
var
OpenDialog: TOpenDialog;
begin
//Carrega a janela para procurar o Imagem
try
OpenDialog := TOpenDialog.Create(nil);
if OpenDialog.Execute then
begin
edtDescricao.Clear;
Caminho := OpenDialog.FileName;
imgImagem.Picture.LoadFromFile(Caminho);
end;
finally
FreeAndNil(OpenDialog);
end;
end;
Listagem 5: Exibe os 3 procedimentos INCLUSÃO, ALTERAÇÃO E EXCLUSÃO
/Procedimento para incluir imagem no banco
procedure TForm2.IncluirImagem(Descricao: string; var Caminho: string);
begin
try
FSql := 'INSERT INTO IMAGEM (TITULO_IMAGEM, CAMINHO_IMAGEM)VALUES(:DESC, :CAMINHO)';
qryAux := TSQLQuery.Create(nil);
qryAux.SQLConnection := FConexao;
qryAux.Close;
qryAux.SQL.Clear;
qryAux.SQL.Add(FSql);
qryAux.Params[0].AsString := Descricao;
qryAux.Params[1].AsString := Caminho;
FReturn := qryAux.ExecSQL();
if FReturn > 0 then
ShowMessage('Registro gravado com sucesso!');
CarregaGrid();
finally
FreeAndNil(qryAux);
end;
end;
//Procedimento para alterar imagem no banco
procedure TForm2.AlterarImagem(Id: integer; Descricao: string; var Caminho: string);
begin
try
FSql := 'UPDATE IMAGEM SET TITULO_IMAGEM=:DESC, CAMINHO_IMAGEM=:CAMINHO WHERE ID=:ID';
qryAux := TSQLQuery.Create(nil);
qryAux.SQLConnection := FConexao;
qryAux.Close;
qryAux.SQL.Clear;
qryAux.SQL.Add(FSql);
qryAux.Params[0].AsString := Descricao;
qryAux.Params[1].AsString := Caminho;
qryAux.Params[2].AsInteger := Id;
FReturn := qryAux.ExecSQL();
if FReturn > 0 then
ShowMessage('Registro alterado com sucesso!');
CarregaGrid();
finally
FreeAndNil(qryAux);
end;
end;
//Procedimento para exclusão do registro
procedure TForm2.ExcluirImagem(Id: integer);
begin
try
FSql := 'DELETE FROM IMAGEM WHERE ID = :ID';
qryAux := TSQLQuery.Create(nil);
qryAux.SQLConnection := FConexao;
qryAux.Close;
qryAux.SQL.Clear;
qryAux.SQL.Add(FSql);
qryAux.Params[0].AsInteger := Id;
qryAux.ExecSQL();
CarregaGrid();
imgImagem.Picture := nil;
finally
FreeAndNil(qryAux);
end;
end;
Listagem 6: Exibe o procedimento para carregar as informações no DBGrid
//Procedimento para exibir os dados no DBGrid
procedure TForm2.CarregaGrid;
begin
try
FSql := 'SELECT ID, TITULO_IMAGEM AS TITULO, CAMINHO_IMAGEM AS CAMINHO FROM IMAGEM';
//Verfica se já existe um objeto TSQLQuery intânciado
if not Assigned(qryDados) then
begin
qryDados := TSQLQuery.Create(nil);
qryDados.SQLConnection := FConexao;
end;
//Verfica se já existe um objeto TDataSetProvider intânciado
if not Assigned(dspDados) then
dspDados := TDataSetProvider.Create(nil);
//Verfica se já existe um objeto TClientDataSet intânciado
if not Assigned(cdsDados) then
begin
cdsDados := TClientDataSet.Create(nil);
cdsDados.ProviderName := dspDados.Name;
cdsDados.PacketRecords := -1;
cdsDados.AfterScroll := Self.CarregarImagem;
end;
//Verfica se já existe um objeto TDataSource intânciado
if not Assigned(dtsDados) then
dtsDados := TDataSource.Create(nil);
//Prepara a qryDados
qryDados.Close;
qryDados.SQL.Clear;
qryDados.SQL.Add(FSql);
qryDados.Open;
//Atribui o objeto qryDados a propriedade DataSet do Provider
dspDados.DataSet := qryDados;
//Prepara o ClientDataSet
cdsDados.Close;
cdsDados.SetProvider(dspDados.DataSet);
cdsDados.Open;
//Atribui o objeto cdsDados a propriedade DataSet do DataSource
dtsDados.DataSet := cdsDados;
//Seta a propriedade DataSource do DBGrid
grdImagem.DataSource := dtsDados;
Except
on E:Exception do
ShowMessage('Erro ao carregar dados no DBGrid!'#13#10 + E.Message);
end;
end;
Listagem 7: Exibe o procedimento carregar a imagem no TImage
//Procedimento para carregar a imagem no imgImagem
procedure TForm2.CarregarImagem(DataSet: TDataSet);
begin
//Verifica se o caminho da imagem é válido
if FileExists(DataSet.Fields[2].AsString) then
begin
imgImagem.Picture.LoadFromFile(DataSet.Fields[2].AsString);
edtDescricao.Text := DataSet.Fields[1].AsString;
end
else
begin
imgImagem.Picture := nil;
edtDescricao.Clear;
end;
end;
Observação: Nesse código não estou aplicando algumas boas práticas de programação, conceitos de POO como encapsulamento para alguns atributos e etc. também não foram verificados. Quanto a trabalhar com componentes em RunTime no próprio portal DevMedia existem excelente artigos e vídeos - aulas sobre esse tema.
Todos os procedimentos estão comentados, mas destaco o código da listagem 7 onde é verificado se o caminho da imagem que está gravado no banco é valido e posteriormente carrega essa imagem no componente imgImage, notem que atribuo esse procedimento ao evento AfterScroll na criação do objeto cdsDados para que sempre que o cursor mudar de registro seja carregado a imagem do atual registro. Esse evento resume perfeitamente o objetivo desse artigo, ou seja, simplesmente gravamos o caminho para a imagem e mesmo assim podemos obter uma boa performance da aplicação para visualizar tais imagens.
Após executarmos a aplicação podemos observar que clicando sobre o registro desejado no DBGrid será alterada a imagem na tela, essas imagens foram selecionadas apenas para testar o funcionamento.
Figura 2: Exibe imagem após seleção do registro no DBGrid
Bom pessoal, demonstrei nesse artigo como pode ser simples gravar somente o caminho das imagens no banco e posteriormente exibi-las, essa prática pode ser muito interessante para diversos tipos de aplicações, eu mesmo já usei.
Com isso finalizo mais um artigo, espero que tenham apreciado e até a próxima.
Qualquer dúvida meu e-mail: wllfl@ig.com.br
Abraços...