Fórum Progress Animado #263784

30/12/2004

0

alguém já precisou fazer uma tela de espera animada?

Tipo o sistema vai processar algo que pode demorar alguns segundos e tu exibe um progress (como o da entrada do xp) enquanto o usuário aguarda o retorno da aplicação.
Tentei montar algo com um timer para a pintura dos painéis e as vezes nem o form é exibido a tempo. Tentei métodos como refresh, uptdate, repaint e ProcessMesages e nada.

Minha próxima alternativa é utilizar threads.

Alguém tem outra idéia?
obrigado


Andremuller

Andremuller

Responder

Posts

30/12/2004

Vinicius2k

Colega,

Vc está no caminho certo... eu esbarrei neste problema há algum tempo e dois colegas de fórum (Beepe e Vini) me ajudaram com a dica e eu montei a unit do form abaixo :
unit unt_VDOPrintProgress;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  StdCtrls, ExtCtrls;

type
  Tfrm_VDOPrintProgress = class(TForm)
    tim_printing: TTimer;   
    bvl_main: TBevel;    
    lbl_printing: TLabel;    
    ptb_printing: TPaintBox; 
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure tim_printingTimer(Sender: TObject);
    procedure ptb_printingPaint(Sender: TObject);
  private
    { Private declarations }
    Frames: TBitmap;
    FrameIndex: Byte;
  public
    { Public declarations }
  end;

var
  frm_VDOPrintProgress: Tfrm_VDOPrintProgress;

implementation

{$R *.dfm}
{$R VDOPrintProgress.res}

procedure Tfrm_VDOPrintProgress.FormCreate(Sender: TObject);
begin
  Frames := TBitmap.Create;
  Frames.LoadFromResourceName(HInstance,´PRINTING´);
  FrameIndex := 0;
end;

procedure Tfrm_VDOPrintProgress.FormShow(Sender: TObject);
begin
  DoubleBuffered := True;
  tim_printing.Enabled := True;
end;

procedure Tfrm_VDOPrintProgress.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Frames.Free;
end;

procedure Tfrm_VDOPrintProgress.tim_printingTimer(Sender: TObject);
begin
  ptb_printing.Refresh;
  if FrameIndex > 5 then FrameIndex := 0;
end;

procedure Tfrm_VDOPrintProgress.ptb_printingPaint(Sender: TObject);
begin
  with ptb_printing.Canvas do
  begin
    Brush.Color := Color;
    FillRect(Bounds(0, 0, 32, 32));
    BrushCopy(Bounds(0, 0, 32, 32), Frames, Bounds(FrameIndex * 32, 0, 32, 32), clFuchsia);
  end;
end;

end.


Neste unit eu estou carregando um bitmap chamado PRINTING de um arquivo de recursos (.res) dividido de forma lógica em 6 frames de 32x32 e com fundo clFuchsia :
[img:28e785c531]http://img97.exs.cx/img97/3967/printing.png[/img:28e785c531]

A vantagem de utilizar um arquivo de recursos é que o bitmap é incorporado à aplicação, e como é pequeno não ´pesa´.
Os componentes que vc irá utilizar são um TTimer e um TPaintBox.
Vc vai escrever nos eventos OnCreate, OnShow e OnClose do TForm, no evento OnTimer do TTimer e no evento OnPaint do TPaintBox.

O efeito final é identico ao de um gif :
[img:28e785c531]http://img97.exs.cx/img97/7441/Printing.gif[/img:28e785c531]

Espero ter ajudado.
T+


Responder

Gostei + 0

30/12/2004

Andremuller

obrigado pela dica amigo mas está dando erro: duplicate resource(s)

quando retiro a declaração do segundo recurso não ocorre erro, mas, é claro, não carrega o bitmaç.

Primeiro tentei utilizar o res do projeto, como deu erro eu criei um res separado mas o erro persistiu.

Alguma idéia?


Responder

Gostei + 0

30/12/2004

Vinicius2k

Colega,

Vc não pode utilizar o .res do projeto porque o recurso é, simplesmente, ignorado na compilação (não sei o motivo). Então vc deve ter recebido a exceção EResNotFound.
Vc precisa do resource separado e as suas opções são:
1. Incluir a linha de acrescimo do recurso no projeto (.dpr)
...
uses
  Forms,
  Unit1 in ´Unit1.pas´ ;

{$R *.res}
{$R SeuArquivo.res}
 
begin
  Application.Initialize;
...

2. Incluir a linha de acrescimo do recurso no próprio form.
...
var
  Form1: TForm1;

implementation

{$R *.dfm}
{$R SeuArquivo.res}
 
procedure TForm1...

Mas apenas uma das duas opções deve ser utilizada, caso contrário você terá o erro de duplicação de recursos. E qualquer que seja a opção, vc não terá erro.
Lembre-se de retirar o bitmap do .res da aplicação, pois ocuparia um espaço desnecessário.

T+


Responder

Gostei + 0

30/12/2004

Andremuller

o problema do res está resolvido. Deixei só no projeto e não declarei no form. Está carregando legal (não foi ignorado na compilação).

Agora acontece o primeiro problema, a imagem não inicia a animação (o forma está aparecendo).

Para testar a animação executo o seguinte código:

procedure TForm1.Button1Click(Sender: TObject);
begin
  form2.show;
  Processa;
  Form2.Close;
end;

procedure TForm1.Processa;
var
  i, j, h: integer;
begin
  h := 0;
  for i := 0 to 10000 do
    for j := 0 to 200000 do
      inc(h);
  Caption := IntToStr(h);
end;


O negócio é que aqui na empresa utilizamos um componente proprietário que funciona nessa mesma rotina.


Responder

Gostei + 0

30/12/2004

Vinicius2k

Colega,

Vc teria que alterar sua procedure ´Processa´ desta forma :
procedure TForm1.Processa;
var
  i, j, h: integer;
begin
  h := 0;
  for i := 0 to 10000 do
    for j := 0 to 200000 do
      begin
        inc(h);
        Application.ProcessMessages;
      end;
  Caption := IntToStr(h);
end;


Mas atenção : Esta chamada à Application.ProcessMessages comprometerá, e muito, a performance desta rotina na forma em que ela está estruturada... o processador, provavelmente, ficará em pico de 100¬ de utilização e o tempo de processamento irá crescer bastante... dependendo do que vc for fazer, é preferível não utilizar a animação.

Se o processamento da rotina for local, na minha opinião vc não deve utilizar, ou procurar outra alternativa. Como vc mesmo citou as Threads, talvez elas sejam melhor aplicáveis neste caso -- não sei lhe dizer pois não trabalho com Threads.

Se o processamento for no servidor, por exemplo, vc envia a consulta e enquanto aguarda o retorno do SGBD vc exibe a animação, não haverá comprometimento...

T+


Responder

Gostei + 0

23/03/2006

Marcos Fernando

Se o processamento for no servidor, por exemplo, vc envia a consulta e enquanto aguarda o retorno do SGBD vc exibe a animação, não haverá comprometimento... 


mais enquanto espero o retorno minha aplicação fica congelada.

e não achei exemplos com threads e banco de dados, até fiz uma tela de testes com threads em um ProgressBar1 que fica achendo e zerando só pra mostrar que a aplicação não está congelada, mais quando eu mando abrir a tabela o ProgressBar1 para de contar

Alguém tem alguma exemplo com banco de dados e threads

Thanks


Responder

Gostei + 0

27/03/2006

Rafael Gomes

olá amigos, aproveitando o topico, alguem saberia me dizer como fazer uma [b:bd5ea75028]barra de progressão [/b:bd5ea75028]que mostre quanto foi baixado de um [b:bd5ea75028]arquivo via ftp[/b:bd5ea75028]!?

ah, depois quando chegar no trampo posto um exemplo de barra de progressao utilizando Thread ..

ate mais
[]s


Responder

Gostei + 0

27/03/2006

Marcos Fernando

ah, depois quando chegar no trampo posto um exemplo de barra de progressao utilizando Thread .. 


Só que preciso de um exemplo com Thread com banco de dados

thanks


Responder

Gostei + 0

27/03/2006

Rafael Gomes

caro colega [b:65043e42f7]Marcos Fernando [/b:65043e42f7]... o exemplo que tinha sabe -se como sumiu de meu micro, mas hoje por sorte estava escrevendo algumas rotinas para gerar um script de inserts gigantescos, dai resolvi criar uma barrinha de progressao somente para testar ...

seria mais ou menos isso ...

aqui é a unit onde esta a thread

unit UProgress;

interface
  uses
    classes, windows, uscript, sysutils, unit2;
  type
    TThreadBanco = class (TThread)
    public
      Constructor create;
    private

    protected
      procedure Execute; override;
end;


implementation

constructor TThreadBanco.create;
begin
  inherited Create(False);
end;

procedure TThreadBanco.Execute;
var
  x: integer;
begin
  form2.show;
  //aqui vai o codigo a ser executado pela thread
  for x:= 0 to 99999 do
    form2.Gauge1.progress:= x; 
 form2.close;
end;

...


para chamar a thread, imagino que voce ja saiba mas fica aqui para quem nao sabe, talvez até mesmo eu esteja fazendo bobagem hehehe, se for o caso me corrijam!

procedure TForm1.Button6Click(Sender: TObject);
var
  T: TThreadBanco;
begin
  T:= TThreadBanco.create;
  T.WaitFor;
  T.Free;
end;


aqui funcionou perfeitamente, enquanto o programa gera os inserts a barra vai subindo de acordo com o que ja foi processado ...
creio que o principio é o mesmo por exemplo se voce quisesse fazer uma rotina para inserir no banco de dados e fossem muitos registros ...

sou iniciante, caso tenha falado alguma bobagem me corrijam
espero ter ajudado,
qualquer coisa é só chamar!

[..]s


Responder

Gostei + 0

27/03/2006

Marcos Fernando

vc usa essa TThread para fazer informar o progresso dos registros incluidos tabela através de um script tá certo, só estou com dúvidas que se puder me esclarecer,

na sua TThread vc tem um for assim:
 //aqui vai o codigo a ser executado pela thread 
  for x:= 0 to 99999 do 


qual é a informação que vc pega da script para passar no for?
e como devo inicializar o script junto com o TThread?
e se fosse com um Ibdataset?

grato mesmo pela força


Responder

Gostei + 0

29/03/2006

Rafael Gomes

[quote:ca142f9261=´Marcos Fernando´]vc usa essa TThread para fazer informar o progresso dos registros incluidos tabela através de um script tá certo, só estou com dúvidas que se puder me esclarecer,

na sua TThread vc tem um for assim:
 //aqui vai o codigo a ser executado pela thread 
  for x:= 0 to 99999 do 


qual é a informação que vc pega da script para passar no for?
e como devo inicializar o script junto com o TThread?
e se fosse com um Ibdataset?

grato mesmo pela força[/quote:ca142f9261]


desculpe a demora amigo, nao havia abandonado o topico ... falta de tempo mesmo ...

pra fazer essa barra de progressao estou partindo do principio que sei quantos registros serao inseridos ...

no meu caso eu tenho todos os inserts em um arquivo texto ...

carrego o arquivo em uma TStringList e depois vou inserindo um a um ... o controle da progressao é a variavel x ....

for x:= 0 to VariaveldoTipostringlist.count - 1 do ;
           begin
             qy.Close;
             qyclear;
             qy.sql.text:= VariaveldoTipostringlist.strings[x];
             qy.Open
           end;


agora a respeito do ibdataset, nunca usei ... mas creio que voce possa adaptar para usar de forma semelhante ...

vi alguem perguntando como faria para fazer uma barra de progressao durante o carregamento de uma query com muitos registro sem travar o programa ... isso eu nao sei como fazer, pq nao sei que valor pegar para saber quantos registros foram carregados e quantos ainda faltam .. nao sei se dentro desse contexto poderia usar recordcount, mas acho que nao .... vou pesquisar ... as vezes pode ate ser bobo e nao estou enxergando ... se laguem souber como fazer poste por favor!

[]ss


Responder

Gostei + 0

29/03/2006

Marcos Fernando

Grato pela atenção [b:d1b3e8618d]Rafael Gomes[/b:d1b3e8618d]

vou procurar mais a respeito, posso usar suas dicas em alguns caso, isso já ajuda muito, agora falta pouco, mais como já falei vou procurar...


Thanks


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar