Foros Club Delphi

Foros Club Delphi (http://www.clubdelphi.com/foros/index.php)
-   FireMonkey (http://www.clubdelphi.com/foros/forumdisplay.php?f=50)
-   -   OnClick dinamicamente (http://www.clubdelphi.com/foros/showthread.php?t=93234)

barakuda 24-06-2018 20:36:15

OnClick dinamicamente
 
Hola a tod@.

Verán hace tiempo hice un programa donde utilizaba la propiedad OnClick de los TImages de las imágenes que cargaba para, mostrar un mensaje, ir a una dirección de Internet... esto lo hacia de forma estática y en tiempo de ejecución mostraba la imagen mediante el Bitmap.LoadFromFile().
Con ganas de mejorar quiero hacer esto mismo pero dinamicamente:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
var
  ListadeObjetos: Tlist;
  I: Integer;

begin

  ListadeObjetos := Tlist.Create();

  for I := 0 to 3 do
  begin
    ListadeObjetos.Add(TImage.Create(Form1));

    with TImage(ListadeObjetos.Items[i]) do
    begin
      Parent := HorzScrollBox1;
      Height := 100;
      Width := 100;
      Bitmap.LoadFromFile(GetCurrentDir + '\' + (I + 1).ToString + '.png');
      with Margins do
      begin
        Bottom := 5;
        Left := 5;
        Right := 5;
        Top := 5;
      end;

      MarginWrapMode := MarginWrapMode.iwStretch;
      Align := Align.alLeft;
      OnClick := pppClick;
    end;

  end;

end;

Código Delphi [-]
  public
    { Public declarations }
    procedure pppClick(Sender: TObject);

Código Delphi [-]
procedure TForm1.pppClick(Sender: TObject);
begin
    showmessage('prueba Imagen:');
end;

Al ejecutar lo que consigo es siempre el mismo mensaje ''prueba Imagen' pero mi intención es que cada imagen que creo le pase (no se como) un showmessage('Timage:'+xx ) diferente a la propiedad OnClick.

¿Pueden echarme una mano con esto por favor?.

Neftali [Germán.Estévez] 25-06-2018 09:56:49

Cita:

Empezado por barakuda (Mensaje 527294)
Al ejecutar lo que consigo es siempre el mismo mensaje ''prueba Imagen' pero mi intención es que cada imagen que creo le pase (no se como) un showmessage('Timage:'+xx ) diferente a la propiedad OnClick.


Para ello puedes usar el parámetro Sender, que será diferente para cada imagen sobre la que pulses. En realidad ese Sender será exactamente el componente TImage sobre el que has pulsado.
Lo único que debes hacer es realizar un CAST del objeto Sender para poder utilizarlo.
Cambia tu código y prueba esto:


Código Delphi [-]
procedure TForm1.pppClick(Sender: TObject); begin
  if (Sender = TImage) then begin
    showmessage('prueba Imagen: ' + TImage(Sender).Name);
  end;
end


Igual que he accedido à la propiedad Name, puede acceder al resto del componente.

barakuda 25-06-2018 12:05:17

Muchas gracias Neftali por tu ayuda, la modificación que me sugeriste me daba error:
Código Delphi [-]
[dcc32 Error] uni_LO.pas(83): E2015 Operator not applicable to this operand type

Lo modifique:
if (Sender = TImage(sender)) then ....

y ahora me funciona.

dejo el código por si a otro compañero le ocurre lo mismo.
Código Delphi [-]
....
  private
    { Private declarations }

    procedure pppClick(Sender: TObject);
...

procedure TForm1.Button1Click(Sender: TObject);
var
  ListadeObjetos: Tlist;
  I: Integer;

begin

  ListadeObjetos := Tlist.Create();

  for I := 0 to 3 do
  begin
    ListadeObjetos.Add(TImage.Create(Form1));

    with TImage(ListadeObjetos.Items[i]) do
    begin
      Parent := HorzScrollBox1;
      Height := 100;
      Width := 100;
      Bitmap.LoadFromFile(GetCurrentDir + '\' + (I + 1).ToString + '.png');
      with Margins do
      begin
        Bottom := 5;
        Left := 5;
        Right := 5;
        Top := 5;
      end;
      Name:='Imagen'+(i+1).ToString;
      MarginWrapMode := MarginWrapMode.iwStretch;
      Align := Align.alLeft;
      OnClick := pppClick;

    end;

  end;

end;

procedure TForm1.pppClick(Sender: TObject);
begin
  if (Sender = TImage(sender)) then begin
    showmessage('prueba Imagen: ' + TImage(Sender).Name);
  end;

end;

Nos obstante una consulta, si cada imagen fuera ligada a una url, una reproducción de sonido, otra imagen etc... es decir a algo mas trascendente ¿seria posible asignar ese "evento" a su correspondiente imagen cuando se crea el objeto TImage?, me explico...

En una BBDD tenemos X fotos esas fotos están ordenadas y se corresponden con el sonido Y cuya dirección esta almacenada también en la BBDD de manera que:
Foto1 -> c:\.....\animales\leonsabana.wav
Foto2 -> c:\.....\motorV6.wav
...

Corrígeme por favor si me equivoco, para conseguir esto, como TImagen no tiene una propiedad para almacenar texto, ¿debería sobrecargar la clase?.

De nuevo muchas gracias por echarme una mano.

Neftali [Germán.Estévez] 25-06-2018 13:15:52

Perdón. He cometido un error en el código al escribirlo.
En lugar de esto:


Código Delphi [-]
procedure TForm1.pppClick(Sender: TObject); 

begin
  if (Sender = TImage) then begin
    showmessage('prueba Imagen: ' + TImage(Sender).Name);
  end;
end;


Quería poner esto (es importante el operador IS en lugar del =):


Código Delphi [-]
procedure TForm1.pppClick(Sender: TObject); 

begin
  if (Sender is TImage) then begin
    showmessage('prueba Imagen: ' + TImage(Sender).Name);
  end;
end;


Con eso comprobamos que el Sender sea de la clase correcta.
No debería, pero eso evita que falle la línea siguiente al realizar el CAST:


Código Delphi [-]
...
  TImage(Sender)
...

Neftali [Germán.Estévez] 25-06-2018 13:24:17

Cita:

Empezado por barakuda (Mensaje 527297)
Corrígeme por favor si me equivoco, para conseguir esto, como TImagen no tiene una propiedad para almacenar texto, ¿debería sobrecargar la clase?.


No la tienen, como bien dices.
Si con un Integer te vale, los TImage y el resto de componentes poseen una propiedad genérica para estas cosas llamada Tag. Que los programadores solemos usar para estas cosas.


La otra opción, como bien dices, es ampliar la clase para añadir esa propiedad.

barakuda 25-06-2018 13:54:12

De nuevo gracias por la sugerencia y aclaración, no pensé en la propiedad Tag la cual se podría utilizar como una especie de puntero hacia a una lista.

Muchas gracias por tu ayuda.^\||/

cloayza 26-06-2018 21:04:33

Estimado barakuda, si me permite le propongo otra opción...

Este método lo he usado cuando requiero mostrar imagenes en algunas aplicaciones...

Consiste en utilizar un TListview y TImageList...

Código Delphi [-]
unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.ImgList,
  Vcl.ExtCtrls, Vcl.Imaging.pngimage;

type
{Tipo de datos que usted puede definir para incorporar mas detalles a cada imagen}
  PInfoImg=^TInfoImg;
  TInfoImg=Record
    Title:string;
    Description:string;
    FileName:string;
    Url:string;
  End;

  TForm2 = class(TForm)
    ImageList: TImageList;
    ListView: TListView;
    Label1: TLabel;
    AddImagen: TButton;
    DeleteImagen: TButton;
    lblTitle: TLabel;
    lblDescription: TLabel;
    lblFilename: TLabel;
    lblUrl: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure ListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
    function CreateBitmap(Filename:string):TBitmap;
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

{Esta función crea un bitmap a partir de un nombre de archivo de imagen
}
function TForm2.CreateBitmap(Filename:string):TBitmap;
var
   picture:TPicture;
begin
     Try
        picture:=TPicture.Create;
        picture.LoadFromFile(Filename);

        Result := TBitmap.Create;
        Result.Assign(Picture.Graphic);

        picture.Free;
     except
        Result:=nil;
     End;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
     Listview.LargeImages:=ImageList;
     Listview.ViewStyle  :=vsIcon;
end;

procedure TForm2.AddImagenClick(Sender: TObject);
var
   FileName:string;
   imgInfo:PInfoImg;
begin
     if not PromptForFileName(Filename,'Png (*.png)|*.png|Bitmap (*.bmp)|*.bmp',
                                       '*.png','Agregar imagen','',false) then
        Exit;
     {Agrego la imagen a el ImageList...}
     ImageList.Add( CreateBitmap(FileName), nil);

     {Creo un puntero para almacenar mas información}
     imgInfo:=New(PInfoImg);
     imgInfo^.Title      :=Format('Imagen %d',[ListView.Items.Count]);
     imgInfo^.Description:=Format('Descripción Imagen %d',[ListView.Items.Count]);
     imgInfo^.FileName   :=Filename;
     imgInfo^.Url        :=Format('https://www.google.com?img=%s',[extractfilename(filename)]);

     with ListView.Items.Add do
     begin
          {Agrego un item y asigno el Title a Caption}
          Caption:=imgInfo^.Title;
          {En Data asigno el puntero con la informacion de la imagen}
          Data:=imgInfo;
          {Asigno el indice de la imagen}
          ImageIndex:=ImageList.Count-1;
     end;
end;

procedure TForm2.ListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
begin
     {Cada vez que pincho un item del Listview recupero los datos desde Item.Data}
     lblTitle.Caption      :=PInfoImg(Item.Data)^.Title;
     lblDescription.Caption:=PInfoImg(Item.Data)^.Description;
     lblFilename.Caption   :=PInfoImg(Item.Data)^.FileName;
     lblUrl.Caption        :=PInfoImg(Item.Data)^.Url;
end;
end.

La imagen adjunta muestra el resultado...


Espero le ayude...
Saludos cordiales

cloayza 26-06-2018 21:53:03

Estimado barakuda, no me percate que era en foro de Firemonky, talvez el código que le indique no funcione correctamente...:(


La franja horaria es GMT +2. Ahora son las 12:34:15.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi