2

表明应用程序正在做某事的最佳解决方案是什么?

我尝试显示进度指示器,但它不起作用。

更新: - - - - - - -

进度条工作正常,但不是我想要的。

我想展示一个throbber,就像 Web 浏览器使用的一样,所以只要有东西在更新,它就一直在转动。

光标也可以处于 crHourGlass 模式。

4

6 回答 6

8

试试这个:

动画单元

unit AnimateUnit;

interface

uses
  Windows, Classes;

type
  TFrameProc = procedure(const theFrame: ShortInt) of object;

  TFrameThread = class(TThread)
  private
    { Private declarations }
    FFrameProc: TFrameProc;
    FFrameValue: ShortInt;
    procedure SynchedFrame();
  protected
    { Protected declarations }
    procedure Frame(const theFrame: ShortInt); virtual;
  public
    { Public declarations }
    constructor Create(theFrameProc: TFrameProc; CreateSuspended: Boolean = False); reintroduce; virtual;
  end;

  TAnimateThread = class(TFrameThread)
  private
    { Private declarations }
  protected
    { Protected declarations }
    procedure Execute(); override;
  public
    { Public declarations }
  end;

var
  AnimateThread: TAnimateThread;

implementation

{ TFrameThread }
constructor TFrameThread.Create(theFrameProc: TFrameProc; CreateSuspended: Boolean = False);
begin
  inherited Create(CreateSuspended);
  FreeOnTerminate := True;
  FFrameProc := theFrameProc;
end;

procedure TFrameThread.SynchedFrame();
begin
  if Assigned(FFrameProc) then FFrameProc(FFrameValue);
end;

procedure TFrameThread.Frame(const theFrame: ShortInt);
begin
  FFrameValue := theFrame;
  try
    Sleep(0);
  finally
    Synchronize(SynchedFrame);
  end;
end;

{ TAnimateThread }
procedure TAnimateThread.Execute();
var
  I: ShortInt;
begin
  while (not Self.Terminated) do
  begin
    Frame(0);
    for I := 1 to 8 do
    begin
      if (not Self.Terminated) then
      begin
        Sleep(120);
        Frame(I);
      end;
    end;
    Frame(0);
  end;
end;

end.

单元1

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ImageList1: TImageList;
    Image1: TImage;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure UpdateFrame(const theFrame: ShortInt);
  end;

var
  Form1: TForm1;

implementation

uses
  AnimateUnit;

{$R *.DFM}
procedure TForm1.UpdateFrame(const theFrame: ShortInt);
begin
  Image1.Picture.Bitmap.Handle := 0;
  try
    ImageList1.GetBitmap(theFrame, Image1.Picture.Bitmap);
  finally
    Image1.Update();
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  AnimateThread := TAnimateThread.Create(UpdateFrame);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  AnimateThread.Terminate();
end;

end.

图片

图像1 图2 图3 图4 图5 图6 图7 图8

动画1

于 2011-04-29T16:34:30.400 回答
6

您可能正在主线程中运行耗时的任务。

一种选择是将其移动到允许为您的消息队列提供服务的后台线程。您需要对其进行维护,以使您的进度条以及任何 UI 都能正常工作。

于 2011-04-29T10:20:07.477 回答
4

回答更新的问题:

  • 生成动画 gif,例如这里
  • 将 GIF 库添加到您的环境 (JEDI JVCL+JCL)
  • 插入一个 TImage 并加载生成的 gif
  • 如果需要,让它可见
于 2011-04-29T12:37:05.813 回答
1

一个指标OK。更改后必须调用Application.ProcessMessages

于 2011-04-29T10:05:40.237 回答
0

“表明该应用程序正在做某事的最佳解决方案是什么?” - 将鼠标光标设置为 crHourGlass?或创建另一个表单/框架/等来提醒用户应用程序正在“做”某事,他需要等待。

于 2011-04-29T11:01:05.250 回答
0

从您的冗长任务中,您偶尔可以更新视觉指示器,例如进度条或其他任何内容。Update但是,您需要通过调用提供反馈的控件立即重绘更改。

不要使用Application.ProcessMessages,因为这会引入可能的重入问题。

于 2011-04-30T12:40:20.610 回答