Mostrando entradas con la etiqueta imagen. Mostrar todas las entradas
Mostrando entradas con la etiqueta imagen. Mostrar todas las entradas

jueves, 20 de febrero de 2020

TBitButton: cambiar imagen.

Se trata de cambiar la imagen de un botón TBitButton en tiempo de ejecución (o mediante código). En este caso las imágenes las obtenemos de TImageList y, como ejemplo, algo básico como un botón para ocultar o mostrar.


Al ejecutar el programa se tiene que ver algo así, un TMemo, que será el elemento del formulario a mostrar y ocultar, y un TBitButton que cambiará la imagen y el texto cada vez que se presione.

unit Unit1;

{$mode objfpc}{$H+}

interface

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

type

{ TForm1 }

TForm1 = class(TForm)
  BitBtn1: TBitBtn;
  ImageList1: TImageList;
  Memo1: TMemo;
  procedure BitBtn1Click(Sender: TObject);
  procedure FormCreate(Sender: TObject);
private
  FOcultar:Boolean;
end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
  FOcultar:=True;
  ImageList1.GetBitmap(0,BitBtn1.Glyph);
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
begin
  if FOcultar then
  begin
    ImageList1.GetBitmap(1,BitBtn1.Glyph);
    BitBtn1.Caption:='Mostrar';
    Memo1.Visible:=False;
  end
 else
 begin
   ImageList1.GetBitmap(0,BitBtn1.Glyph);
   BitBtn1.Caption:='Ocultar';
   Memo1.Visible:=True;
  end;
  FOcultar:=not(FOcultar);
end;

end.


En la variable FOcultar almacenamos el estado del botón.
En el evento FormCreate le asignamos el valor True a FOCultar y le asignamos la imagen correspondiente, en este caso la misma es la primera de TImageList que por cierto, también debemos incluir en el Form.
ImageList1.GetBitmap(0,BitBtn1.Glyph);
Para asignar la primera imagen de la lista, utilizamos el procedimiento GetBitmap de TImageList: el primer parámetro corresponde al índice de la imagen, el segundo, a la imagen destino, en este caso BitBtn1.Glyph.
Porque TBitBtn.Glyph:TBitmap = class(TFPImageBitmap).
El método (procedimiento) GetBitmap pertenece a la clase TCustomImageList:

TCustomImageList.GetBitmap(Index: Integer; Image: TCustomBitmap);

En este ejemplo también cambiamos el texto del botón.
Finalmente cambiamos el valor de FOcultar, sino, no pasa nada.

Si bien es algo sencillo, dejo el código fuente del proyecto: descargar.

viernes, 9 de febrero de 2018

Guardar y leer imágenes en bases de datos.

Además de ver como se guarda una imagen de cualquier formato (JGP, PNG, etc.) en una base de datos SQL (SQLite en este caso), también veremos como leerla y mostrarla en un TImage en un formulario.
Logotipo: TImage;
Al TImage del Form1 lo llamamos Logotipo.
Para leer la imagen y mostrarla en un TImage en un Form:
procedure TFom1.CargoDatos;
var
  unstream:TMemoryStream;
begin
  //Se cargan la campos "normales"...
  if ZQuery1.FieldByName('logo').IsNull then
  begin
    Logotipo.Picture.Clear;
    Exit;
  end;
  unstream:=TMemoryStream.Create;
  unstream.Position:=0;
  TBlobField(ZQuery1.FieldByName('logo')).SaveToStream(unstream);
  unstream.Position:=0;
  Logotipo.Picture.LoadFromStream(unstream);
  unstream.Free;
end;
Declaramos una variable del tipo TMemoryStream donde almacenaremos el contenido de la imagen que se encuentra en el campo "logo" de una tabla.
Para no tener problemas, averiguamos si existe tal imagen, lo hacemos con FieldByName('logo').IsNull. Si esto devuelve True entonces borramos la imagen de LogoTipo, si no hacemos esto quedará la imagen cargada anteriormente si la hubiere. Si IsNull devuelve False quiere decir que hay una imagen (o debería haberla), entonces creamos el stream, lo posicionamos en 0 (cero) y lo cargamos con TBlobField(el campo).SaveToStream y cabe aclarar que no es necesario definir ninguna variable del tipo TBlobField, este procedimiento se encarga de todo. Ahora ya tenemos la imagen del campo logo de una tabla de una base de datos cargada en un stream de memoria, el paso final es mostrarla en el formulario, para eso posicionamos nuevamente a 0 (cero) el stream, y lo mandamos al TImage nombrado Logotipo y no olvidarse de liberar el stream utilizando el método Free.

Ahora lo inverso, leer la imagen y guardarla en la base de datos. Se omite la carga desde archivo en este ejemplo.
procedure TForm1.GuardarDatos(Sender: TObject);
var
  ms:TMemoryStream;
begin
  //Se pone el dataset en modo edit o insert y se graban los 
  //campos "normales"...
  if (logotipo.Picture.Width>0) then
    begin
      ms:=TMemoryStream.Create;
      Logotipo.Picture.SaveToStream(ms);
      ms.Position:=0;
      TBlobField(ZQuery1.FieldByName('logo')).LoadFromStream(ms);
      ms.Free;
    end
  else
    begin
      ZQuery1.FieldByName('logo').AsString:='';
    end;
  ZQuery1.Post;   
end;
Como en el código anterior, necesitamos una variable para el stream en memoria. Y nuevamente para no tener problemas, mediante Logotipo.Picture.Width>0 determinamos si hay alguna imagen que guardar, caso contrario se guarda NULL, AsString:='' hace eso.
Si hay imagen, creamos el stream y le asignamos la imagen que está contenida en la propiedad Picture de Logotipo (TImage). Posicionamos en 0 (cero) el stream que ya contiene la imagen y nuevamente nos valemos de TBlobField que asignará el stream al campo "logo" y liberamos con Free el stream.

Desde ya es un código orientativo, pero testeado que este método funciona, al menos para SQlite utilizando ZeosLib.

Hay muchas formas de hacer esto, pero esta forma es la que menos problemas me trajo y es bastante simple y "limpia". He probado antes con DBImage, pero a veces ejecutando el código desde la IDE me tiraba un error EReadError que podía ignorar y todo seguía bien, de hecho ejecutando el programa (fuera de la IDE) esos errores no se mostraban, hasta que detecté que si la imagen que leía DBImage no era JPG entonces largaba ese error, eso me motivo a deshacerme de TDBImage y hacerlo como lo muestro, básicamente con un stream, el procedimiento TBlobField y un TImage.

domingo, 14 de enero de 2018

LazReport: incluir imagen de campo BLOB

Antes esto era una tarea un poco complicada según pude observar después de varias búsquedas que me mostraban hilos de foros de hace unos cuantos años. Por suerte esto ya no es así e incluir una imagen de cualquier formato (dentro de los más populares) almacenada en un campo o columna del tipo BLOB es tan sencillo que no requiere ni una línea de código.

Desde el diseñador LazReport debemos incluir un objeto del tipo imagen y nos aparecerá el siguiente diálogo:


La opción Cargar es para cargar una imagen contenida en un archivo, no es el caso. Debemos hacer click en Texto.


Y aquí tanto solo indicamos el campo que contiene la imagen. Si el dataset está conectado, podemos agregarlo desde el botón Campo de DB.
Eso es todo.