进度条的设计(oo)(200分)

  • 主题发起人 duhai_lee
  • 开始时间
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
我们写的程序很多 动作都不是 瞬间 完成的, 需要用进度条显示。 如果简单的一个循环,那么可以在循环中加入一个进度条。
可是我们的往往提供给用户的一个操作,在代码中是划分为若干个 功能点实现的, 并且每个阶段可能都需要花费一定时间。 至少应该在每个阶段告诉用户,系统在处理什么,执行了多少。 如果说每个阶段都是一个对象在执行,那么在不同的功能内中,如何加入一个progressbar, 既不影响我们程序设计的独立性, 又可以简洁的完成进度提示呢?
希望看到oo高手们指点迷津。 支持者也有分。
为了方便起见,我举例如下:
有个导入数据库的操作, 用户只需要选择一个zip文件。
而代码中,却是分为, 解压文件, 审核数据正确性, 导入数据库3个阶段。
如何让进度贯穿3个实现,或者如何保持实现类的独立而又可以显示每个阶段的进度。。。。 (不知道我的表述清楚否??)
 
P

Puha

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,很清楚你的意思。。。。
你不想让进度处一个接一个的闪。。
可以参考下WinXp安装时的进度显示方式,3到4个指示框,从左到右,到最右边时又返回到最左边,周而复始。
想让用户知道程序在运行着,这种试最好,(我就是这么干的),只是,用户无法知道还要多长时间。。。[:D]
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢楼上。 我也搞了一个Gif的动画进度条, 在处理前让它显示,可惜它并不“愿意”动弹, 直到事情处理结束。 我也试着在show progress时给它 application.ProcessMessages;
难道必须用线程?
 
C

cb20000

Unregistered / Unconfirmed
GUEST, unregistred user!
先申明偶是菜鸟:(
我先说下我对你问题的理解:
首先一个操作分为三个部分来解决,而这三个部分的关系是线性的,就是运行完一个再执行下一个,对吧?
那首先最重要的问题就是能否获得三个部分的中每个部分的开始和结束的标志,其次是寻找一种合理的办法来表示进度的显示,例如,如何显示解压过程的完成度只类的问题。
 
C

cb20000

Unregistered / Unconfirmed
GUEST, unregistred user!
哦~那我就明白你的问题了,你的问题是你写的代码是个单线程的,在执行的过程中界面几乎不能操作了是吧?估计你要使用线程会比较简单的
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
谢谢 cb20000 的提议。 对于多线程封装我不熟, 需要花点时间研究, 目前是比较忙乱,所以暂时不考虑用线程。
 
C

cb20000

Unregistered / Unconfirmed
GUEST, unregistred user!
需要在线程的执行过程里控制进度条的显示
主窗体有如下控件:
ProgressBar1: TProgressBar;
Label1: TLabel;
tmr: TTimer;
如下事件:
procedure TForm1.tmrTimer(Sender: TObject);
begin
if ProgressBar1.Position<>ProgressBar1.Max then
ProgressBar1.StepIt
else
ProgressBar1.Position:=0;
end;

线程 Execute 加入
if 开始解压 then
begin
tmr.Enabled:=True;
Label1.Caption:='正在解压';
end;
if 解压完毕 then
begin
tmr.Enabled:=False;
Label1.Caption:='解压完毕';
Form1.ProgressBar1.Position:=100;
end;

if 审核数据 then
begin
...
end;
...
...
线程 Terminate 加入
tmr.Enabled:=False;
Label1.Caption:='执行完毕';
Form1.ProgressBar1.Position:=0;
建议把三个部分分别写成线程中的三个过程,在分别顺序执行三个过程前加入进度条的执行部分,在结束后加入进度条的结束部分。
 
C

cb20000

Unregistered / Unconfirmed
GUEST, unregistred user!
不客气,其实也没帮你解决问题:(汗颜:(
 
P

Puha

Unregistered / Unconfirmed
GUEST, unregistred user!
GIF肯定不好使,我听同事说,有控件,不过他不知道叫什么名字,*_*,我就更不知道了。
简单点,让Time控件控制PGS跑,只要在OnTime()中判断是否到MAX()了,是,归0,这种跑马式的进度条只要你们老大首肯就行(偷工呀。。。:)
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
timer控制也出现上述 情况, 自始至终都是不动。
 
K

kgm

Unregistered / Unconfirmed
GUEST, unregistred user!
把费cpu工时的部分放到一个独立线程中。
 
B

Beyondbill

Unregistered / Unconfirmed
GUEST, unregistred user!
采用事件Notify方式最好不过
首先你可以建立一个某个任务的子任务列表,事件Notify代码就实现与进度条的交互
procedure 任务;
begin
子任务A;
子任务B;
end;

procedure 子任务A;
var
nCount : Integer;
begin
nCount := 0;
while (条件)do
begin
完成其中的一个细节;
Inc(nCount);
Notify('子任务A', nCount);
//像这种通知处理过程,你可以根据你的要求进行修改,以下类同
end;
end;

procedure 子任务B;
var
nCount : Integer;
begin
nCount := 0;
while (条件)do
begin
完成其中的一个细节;
Inc(nCount);
Notify('子任务B', nCount);
end;
end;

procedure Notify(任务名, 进度值);
begin
if Assigned(FOnNotify) then
begin
FOnNotify(任务名, 进度值);
//这样处理是方便扩展,你即可以用ProgressBar来显示,同时还可以进行其他的动作
end;
end;

这里我们实现一个自定义的FOnNotify例子
proceduredo
Notify(任务名,进度值);
begin
根据任务名与进度值,显示在ProgressBar上;
其他处理;
end;

通过上面这样处理,你可以大大减少与ProgressBar条的交互,而且以后需要进行其他处理,也非常的方便。甚至你那天你觉得不需要用ProgressBar来显示进度的时候,你可以不用处理FOnNotify事件,就能达到这个目的
 
P

Puha

Unregistered / Unconfirmed
GUEST, unregistred user!
!!,很想帮你,去年也是这个问题把我搞得头大头大的。
我分析一下我出现这个问题的原因:
全线程占用(SAOP,进行时采用全线程占用方式,我E文不好,大概这样译);
处理的数据在那个时候有点多,CPU 100%;
看看你的是不是这样,如果是,我帮不了你,因为我的也这样,如果解决了,记得告诉我一声。。。。(还好,我的是要很多时间,半秒钟,客户能承受)QQ: 308886262 谢谢。
还有,我试过线程了,我的没搞定。你可以参阅一下Delphi下自带的线程进度条示例。找一下,最近用Net,没装Delphi,不能告诉你目录,见谅。
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
感谢各位支持。
Beyondbill 大侠的作法是我以前的作法。 但是我对这种每个任务嵌套的跟踪进度不满意,其实说白了,不用告诉到底完成百分之几,剩余百分之几,只要让他们看到系统在运行,且可以告诉他们是那个阶段就可以了。
Puha 我觉得线程的解决办法也是最好的,但是目前的 主要精力不能放在这个小问题上面,所以才求现成(有点懒)。 如果我有好的方案,一定跟兄弟们分享。
cb20000 提的建议很好。 等我把主要功能搞定,就依照楼上各位兄台指点好好设计一个。
希望大家继续发言。
 
B

Beyondbill

Unregistered / Unconfirmed
GUEST, unregistred user!
呵~,我没有说让你一定告诉他任务套的进度,你完全可以把我那句通知的过程代码放到你每个子任务结束的地方.
这样每个子任务完成,就给一个进度显示:子任务完成数/总的任务数*100%
 
P

Puha

Unregistered / Unconfirmed
GUEST, unregistred user!
这次讨论收获不少。
我可以总结发言了吗?
有几种:
1、分而治之 Beyondbill
2、置之不理 (当然是我的,不过楼主早想到了)
3、同步实施 cb20000(不过有时线程也不能搞定)
总之,楼主,我们浪费了这么多空间,给分吧!!,就等你这句了。(:),我想大家最同意的,觉得最有理的,是这句)
 
B

bbscom

Unregistered / Unconfirmed
GUEST, unregistred user!
作用不大,消耗太多空間了。
 
C

cb20000

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵~Puha很直接哈~
楼主如果需要线程的例子我这里到是有一个,如果需要可以把线程单元发给你:)照葫芦画瓢的应该不难解决:)其实虽然说是多线程,其实执行过程的也就一个线程:)还是比较简单的。
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
Ok, 呵呵:0 放分肯定是主题。 我的邮箱是:duhai_lee@163.com
分不均匀大家别见怪。 [8D]
如果大家意犹未尽的话,我可以另开贴。 或者继续在这里讨论,另开贴送分。
 
D

duhai_lee

Unregistered / Unconfirmed
GUEST, unregistred user!
多人接受答案了。
 
顶部