Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Desarrollo en Delphi para Android (https://www.clubdelphi.com/foros/forumdisplay.php?f=57)
-   -   ProgressBar en ListView (https://www.clubdelphi.com/foros/showthread.php?t=94441)

RebeccaGL 10-02-2020 21:08:13

ProgressBar en ListView
 
Hola, buenas con todos
Hay alguna forma de poner un ProgressBar en un Listview?.

Ñuño Martínez 11-02-2020 20:06:26

¿Te refieres a dentro del ListView? Tal vez asignando el Owner y el Parent del ProgressBar, aunque no sé qué resultado tendrá.

¿No te vale con colocarlo encima y ocultarlo o mostrarlo según se necesite?

bucanero 12-02-2020 17:55:50

hace un tiempo publique este truco
https://www.clubdelphi.com/foros/showthread.php?t=93028
que hace justamente lo que necesitas de forma bastante simplificada, lo que no se es si servirá también para android...

Intenta probarlo y nos cuentas

RebeccaGL 14-02-2020 03:11:46

Buenas Bucanero, le hice unas modificaciones, agregue otras unidades para que funcione para Android, pero aun salen errores como:
Variable Data no existe

Estoy usando Delphi Rio 10.3, quisas sea por las versiones cada vez son diferentes, pero seguire buscando, gracias.

Código Delphi [-]
unit ListItemHelpers;

interface

uses
  Windows, Vcl.ComCtrls,
  FMX.ListView, FMX.ListView.Types, FMX.Grid.Style, FMX.ListView.Appearances,
  FMX.ListView.Adapters.Base, FMX.StdCtrls;

type
  TListItemHelper = class helper for TListItem
  private
    function GetRect(AColumn: Integer): TRect;
    function GetProgressBar: TProgressBar;
  public
    procedure AdjustProgressBar;
    function AddPRogressBar(AColumn: integer = 1): TProgressBar;
    procedure DeleteProgressBar;
    property ProgressBar: TProgressBar read GetProgressBar;
  end;

implementation

uses
  Vcl.Dialogs, System.SysUtils,  System.UITypes;

procedure Error(E:Exception; const msgTxt:String);
begin
  {$IF DEFINED(MSWINDOWS)}
  MessageDlg(E.Message + #13 + msgTxt, mtError, [mbOK], 0);
  {$ENDIF)}
end;

{ TListItemHelper }

function TListItemHelper.AddPRogressBar(AColumn: integer): TProgressBar;
/// Si AColumn es igual 0 entonces se situa en la ultima columna
begin
  if assigned(Data) then begin
    Result := data;
    exit;
  end;
  ///  se le asigna como OWNER del PROGRESSBAR el listView propietario del LISTITEM
  ///  en donde queremos el PROGRESSBAR, para que asi, se libere automaticamente
  ///  tambien al liberar el listView
  result := TProgressBar.Create(TListView);
  /// se le asigna como padre el listView
  result.parent := TListView;
  /// El dobleBuffered evita el parpadeo
  result.DoubleBuffered := true;
  if (AColumn <= 0) then
    AColumn := 1;
  /// El tag del progresBass va a ser el numero de columna
  /// dentro del listItem donde se situa el propio ProgressBar
  result.Tag := AColumn;
  /// se guarda el puntero al ProgressBar en el campo DATA del ListItem
  Data := result;
  AdjustProgressBar;
end;

procedure TListItemHelper.AdjustProgressBar;
var
  pb: TProgressBar;
begin
  pb := Data;  //<-- listItem.data
  if assigned(pb) then
    /// El tag del progresBass va a ser el numero de columna
    /// dentro del listItem donde se situa el propio ProgressBar
    pb.BoundsRect := GetRect(pb.Tag);
end;

procedure TListItemHelper.DeleteProgressBar;
var
  pb: TProgressBar;
begin
  /// al liberar el ProgressBar no se por que da un error,
  /// asi que en principio lo dejo sin liberar.
  /// Aunque queda pendiente de ver por que lo hace.
  /// Tampoco supone un gran problema porque se creo con padre
  /// y ya se encarga el proceso de eliminarlo automaticamente
  try
    pb := Data;
    if assigned(pb) then
    try
      freeAndNil(pb);
      data := Nil;
    except
      on E: Exception do
        error(e, 'TListItemHelper.DeleteProgressBar');
    end;
  except
    on E: Exception do
      error(E, 'TListItemHelper.DeleteProgressBar');
  end;
end;

function TListItemHelper.GetProgressBar: TProgressBar;
begin
  try
    Result := nil;
    if not Assigned(Data) then
      AddPRogressBar;
    result := TObject(Data) as TProgressBar
  except
    on E: Exception do
      Error(E, 'TListItemHelper.GetProgressBar');
  end;
end;

function TListItemHelper.GetRect(AColumn: Integer): TRect;
var
  i: longint;
begin
  result := DisplayRect(drBounds);
  // last column is to take progress bar
  with TListView(ListView) do begin
    if AColumn = 0 then
      AColumn := columns.Count - 1;
    for i := 1 to AColumn do
      result.left := result.left + columns[i - 1].Width;
    result.right := result.Left + columns[AColumn].Width;
  end;
end;

end.

bucanero 17-02-2020 11:49:19

He estado revisando el TLISTVIEW de firemonkey y tiene algunas diferencias con respecto al de la VCL en particular creo que no puedes definir columnas, o no he conseguido ver como se definen. El tema de las columnas en el truco anterior era para determinar la posición del progressbar dentro del listView, al no disponer de esta propiedad, la posición hay que darsela a mano.

Y modificando un poco el código anterior, queda así y con este creo que te debe de funcionar:

Código Delphi [-]
unit ListViewItemHelper;

interface

uses Windows, System.Types, FMX.ListView, FMX.StdCtrls;

type
  TListViewItemHelper = class helper for TListViewItem
  private
    function GetProgressBar: TProgressBar;
    function GetListView: TListView;
    procedure SetProgressBar(const Value: TProgressBar);
    property ListView: TListView read GetListView;
    function AssignedProgressBar:Boolean;
  public
    function AddPRogressBar: TProgressBar; overload;
    function AddPRogressBar(ARectF: TRectF): TProgressBar; overload;
    procedure DeleteProgressBar;
    property ProgressBar: TProgressBar read GetProgressBar write SetProgressBar;
  end;

implementation

uses
  Vcl.Dialogs, System.SysUtils;


procedure Error(E:Exception; const msgTxt:String);
begin
{$IF DEFINED(MSWINDOWS)}
  MessageDlg(E.Message + #13 + msgTxt, mtError, [mbOK], 0);
{$endif}
end;


{ TListItemHelper }

function TListViewItemHelper.AddPRogressBar(ARectF: TRectF): TProgressBar;
begin
  Result := AddPRogressBar;
  if Assigned(result) then
    progressBar.BoundsRect := ARectF;
end;

function TListViewItemHelper.AddPRogressBar: TProgressBar;
begin
  if not AssignedProgressBar then begin
    ///  se le asigna como OWNER del PROGRESSBAR el listView propietario del LISTITEM
    ///  en donde queremos el PROGRESSBAR, para que asi, se libere automaticamente
    ///  tambien al liberar el listView
    ProgressBar := TProgressBar.Create(ListView);
    /// se le asigna como padre el listView
    ProgressBar.parent := ListView;
  end;
  Result := ProgressBar
end;

function TListViewItemHelper.AssignedProgressBar: Boolean;
begin
  Result := (tag <> 0) and assigned(TObject(Tag)) and (TObject(Tag) is TProgressBar);
end;

procedure TListViewItemHelper.DeleteProgressBar;
var
  pb: TProgressBar;
begin
  /// al liberar el ProgressBar no se por que da un error,
  /// asi que en principio lo dejo sin liberar.
  /// Aunque queda pendiente de ver por que lo hace.
  /// Tampoco supone un gran problema porque se creo con padre
  /// y ya se encarga el proceso de eliminarlo automaticamente
  try
    pb := ProgressBar;
    if assigned(pb) then
    try
      freeAndNil(pb);
      ProgressBar := nil;
    except
      on E: Exception do
        error(E, 'TListItemHelper.DeleteProgressBar');
    end;
  except
    on E: Exception do
      error(E, 'TListItemHelper.DeleteProgressBar');
  end;
end;

function TListViewItemHelper.GetListView: TListView;
begin
  result := (Parent as TListView);
end;

function TListViewItemHelper.GetProgressBar: TProgressBar;
begin
  try
    Result := nil;
    if not AssignedProgressBar then
      AddPRogressBar;
    result := (TObject(Tag)as TProgressBar);
  except
    on E: Exception do
      Error(E, 'TListItemHelper.GetProgressBar');
  end;
end;

procedure TListViewItemHelper.SetProgressBar(const Value: TProgressBar);
begin
  if not assigned(Value) then
    Tag := 0
  else
    Tag := Integer(Value);
end;

end.

Y la forma de uso es:

Código Delphi [-]
uses ListViewItemHelper;

var
  MiItem: TListViewItem = Nil;

procedure TForm1.ButtonAddItemClick(Sender: TObject);
begin
  with ListView1.Items do begin
    // añadir un nuevo item al listview
    MiItem := add;
    MiItem.Text := 'mi item';
  end;
end;

procedure TForm1.ButtonAddProgressBarClick(Sender: TObject);
begin
  if Assigned(MiItem) then
    // Insertar un ProgressBar en la posicion requerida
    MiItem.AddPRogressBar(RectF(10, 10, 300, 40));
end;

procedure TForm1.ButtonDeleteProgressBarClick(Sender: TObject);
begin
  if Assigned(MiItem) then
    // eliminar el progressBAr del ITEM
    MiItem.DeleteProgressBar;
end;

Con esto te debería de funcionar

RebeccaGL 19-02-2020 15:10:11

Hola Bucanero y gracias por tu ayuda.
Tu código esta bien ahora solo me da el único error de parent no existe.

bucanero 19-02-2020 17:43:33

1 Archivos Adjunto(s)
Hola RebeccaGL,

Cita:

Empezado por RebeccaGL (Mensaje 535794)
Hola Bucanero y gracias por tu ayuda.
Tu código esta bien ahora solo me da el único error de parent no existe.

Comentas que te da el error de que no existe la propiedad parent, realmente me parece un error un tanto curioso por que al final en el proceso solo se están utilizando dos objetos "estandard" y ambos con la propiedad parent disponible, el TProgressBar y el TlistViewItem.

En particular, ¿en que parte del código te da el error?:
-En la función GetListView el campo parent es el del TlistViewItem y es el que determina el TListView al que pertenece
-Y en la función AddPRogressBar, el parent es el del progressBar y si no lo ajustas entonces no va a ser visible

Código Delphi [-]
function TListViewItemHelper.GetListView: TListView;
begin
  result := (Parent as TListView);
end;

function TListViewItemHelper.AddPRogressBar: TProgressBar;
begin
   ...
    ProgressBar.parent := ListView;
   ...
end;

No se decirte de donde puede venir el error que comentas. Yo estoy haciendo pruebas en delphi XE7 creando un proyecto totalmente en blanco de multi-dispositivos e insertando en el form un TListView con 3 botones y la unidad con el helper tal como esta aquí publicado y funciona sin problemas. Aquí te subo el proyecto para que puedas hacer pruebas con el y nos comentas

RebeccaGL 20-02-2020 18:58:21

ok, gracias lo probare.

RebeccaGL 20-02-2020 19:23:39

Tienes razón Bucanero funciona bien en Delphi XE7, pero yo lo tengo en Delphi Rio 10.3 ahi si me salen errores, gracias de todas maneras por tu esfuerzo.
:)

bucanero 21-02-2020 17:58:57

1 Archivos Adjunto(s)
Hola RebeccaGL,

No había hecho pruebas en Delphi RIO 10.3 hasta ahora y tras mirarlo he visto que han cambiado algunas cosas en cuanto a las propiedades de los componentes, herencias y dependencias. Entre ellos la propiedad parent del TListViewItem ha desaparecido y ahora se accede desde la propiedad Controller, junto a algunos otros detalles, por lo que mi primer código ya no funciona para esa versión.

Modificando los "detalles" que ya he comentado y alguno otro mas, este código ya si es funcional para la versión RIO 10.3

Espero te sirva

RebeccaGL 21-02-2020 20:55:31

Muchas gracias Bucanero, ahora si funciona estoy muy agradecida por tus esfuerzos. Yo no conozco mucho sobre componentes y herencias, pero es algo que estoy aprendiendo. Que tengas muy buen día.


La franja horaria es GMT +2. Ahora son las 23:32:52.

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