Não travar animação igual o TAnimate

Delphi

05/11/2007

Olá galera!

Alguém sabe como fazer uma animação por exemplo, em gif, que não congele em um processamento?

Quando coloco um TAnimate e o ativo, ele não congela a animação. Como é feito? Alguém sabe?

Tentei com o JvBmpAnimator da biblioteca Jedi, que é exatamente o que eu preciso, mas o problema é que ele congela a animação quando inicio algum processo.

Fico aguardando uma dica!

Obrigado desde já!


Tchelllo

Tchelllo

Curtidas 0

Respostas

Alexandrej

Alexandrej

05/11/2007

Olá galera! Alguém sabe como fazer uma animação por exemplo, em gif, que não congele em um processamento? Quando coloco um TAnimate e o ativo, ele não congela a animação. Como é feito? Alguém sabe? Tentei com o JvBmpAnimator da biblioteca Jedi, que é exatamente o que eu preciso, mas o problema é que ele congela a animação quando inicio algum processo. Fico aguardando uma dica! Obrigado desde já!


Se esse processo for por exemplo, um while, você pode tentar colocar um Application.ProcessMessages dentro do looping.


GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

Olá Alexandrej!

Este processo não é um loop. Trabalho com 3 camadas. O que eu faço é disparar um método no servidor a partir da app. cliente. Nesse momento o programa fica congelado até que o método seja finalizado.

Por isso o uso do Application.ProcessMessages não tem como ser executado.


GOSTEI 0
Massuda

Massuda

05/11/2007

O TAnimate (que é apenas uma ´casca´ para um controle do Windows) usa uma thread separada para fazer a animação; se você fizer TAnimate.Timers = True, a animação é feita usando um timer interno do Windows. De qualquer forma, como é algo separado do seu programa, não é afetado pelo processo lento no seu programa.


GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

Massuda, vc teria idéia +- de como esta thread é feita para executar a animação do TAnimate?


GOSTEI 0
Alexandrej

Alexandrej

05/11/2007

Olá Alexandrej! Este processo não é um loop. Trabalho com 3 camadas. O que eu faço é disparar um método no servidor a partir da app. cliente. Nesse momento o programa fica congelado até que o método seja finalizado. Por isso o uso do Application.ProcessMessages não tem como ser executado.


Então uma thread é o ideal mesmo.


GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

Me tirem uma dúvida então:

Quando usamos thread, não podemos fazer desta forma, ex:

procedure Button1Click(Sender: TObject);
var i: integer;
s: string;
begin
IniciaThread;

for i := 0 to 2000000 do
s := IntToStr(i);
end;

No caso a thread fica congelada do mesmo jeito. O correto é da forma abaixo:

procedure Button1Click(Sender: TObject);
begin
IniciaThread;
IniciaLoop;
end;

Nos 2 casos, a thread não era pra ser executada tbm? O que estou fazendo de errado?


GOSTEI 0
Alexandrej

Alexandrej

05/11/2007

Me tirem uma dúvida então: Quando usamos thread, não podemos fazer desta forma, ex: procedure Button1Click(Sender: TObject); var i: integer; s: string; begin IniciaThread; for i := 0 to 2000000 do s := IntToStr(i); end; No caso a thread fica congelada do mesmo jeito. O correto é da forma abaixo: procedure Button1Click(Sender: TObject); begin IniciaThread; IniciaLoop; end; Nos 2 casos, a thread não era pra ser executada tbm? O que estou fazendo de errado?


Você deve criar uma thread passando algum objeto como parâmetro para receber o resultado do processamento. A noite se precisar posso explicar melhor, durante o dia é complicado. :(
Mas existem bastante exemplos no google, digite na busca: delphi + thread + definitivo.


GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

Eu já cheguei a ler essa dica da ´Thread definitiva´. Mas se coloco por exemplo um código depois que iniciei a thread, a mesma congela até o processo terminar.

como no exemplo que dei:

procedure Button1Click(Sender: TObject);
var i: integer;
s: string;
begin
IniciaThread;

for i := 0 to 2000000 do
s := IntToStr(i);
end;

Se fizer assim a thread fica congelada tbm. Não era pra ficar executando?


GOSTEI 0
Massuda

Massuda

05/11/2007

Seu loop for deveria estar no TThread.Execute (assumindo que você esteja usando um objeto de thread derivado de TThread), não onde ele está no seu exemplo. Mostre o que é IniciaThread.


GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

Olá Massuda!

IniciaThread é apenas um exemplo indicando que alí eu estou iniciando uma thread (MinhaThread.Create(False))

O que eu quero exatamente é o seguinte: Mostrar uma tela de espera com animação enquanto executo um método no servidor. A animação é pra mostrar que o programa não está travado.

O correto é eu colocar a chamada ao método na minha thread? E o código que cria a tela de espera com animação? Na Thread tbm ou em uma outra?


GOSTEI 0
Massuda

Massuda

05/11/2007

Geralmente coloca-se o processo demorado numa thread separada, assim a UI do seu programa continua viva. Exemplo bem simples e não testado:
const
  WM_MINHA_THREAD_ACABOU = WM_USER + 1;

type
  TMeuFormPrincipal = class(TForm)
    procedure Button1Click(Sender: TObject);
  private
    procedure WMMinhaThreadAcabou(var Msg: TMessage); message WM_MINHA_THREAD_ACABOU;
    ...
  end;

  TMinhaThread = class(TThread)
  protected
    procedure Execute; override;
    ...
  end;

...

procedure TMinhaThread.Execute;
begin
  FreeOnTerminate := True;

  try
    // faz algo demorado aqui
  except
    // trata eventuais exceções
  end;

  // avisa a UI que terminou
  PostMessage(Application.MainForm.Handle, WM_MINHA_THREAD_ACABOU, 0, 0);
end;

...

procedure TMeuFormPrincipal.Button1Click(Sender: TObject);
begin
  // inicia a animação, desabilita o botão, etc

  // inicia a thread
  TMinhaThread.Create(False);
end;  

procedure TMeuFormPrincipalWMMinhaThreadAcabou(var Msg: TMessage); 
begin
  // pára a animação, habilita o botão, etc
end;



GOSTEI 0
Tchelllo

Tchelllo

05/11/2007

No meu sistema, eu tenho vários métodos demorados onde eu coloco uma tela de espera antes do iniciar.

Teria uma forma mais fácil e rápida de fazer isso ao invés de criar uma thread pra cada método?


GOSTEI 0
POSTAR