如何根据加载进度制作进度条

wubicheng 2013-08-07 05:25:13
如题,怎么样根据当前程序的加载进度来确定进度条的进度?原理是什么?怎么实现?
我在网上搜到的大部分是每隔一个固定时间就增加一个固定的进度值,这样的话进度条好像就没有什么实际意义了吧,不能反映实际的程序加载情况。
而且大部分都是直接使用的进度条控件,呃,那东西实在是太丑了,我打算自己绘制进度条,不用系统的进度条,采用Win32 API实现,要准备两张图片来进行叠加我知道,但是不知道怎么实时反映程序的加载进度,以前写程序都比较小,最近写了个相对来说稍微大了点的程序,资源比较多,程序在运行时启动、切换都有一些延迟,所以想用进度条来遮掩,有没有人知道该怎么去做?
...全文
682 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
陈七安欧巴 2015-08-21
  • 打赏
  • 举报
回复
完成了,能写个Demo分享一下吗?
wubicheng 2013-08-11
  • 打赏
  • 举报
回复
OK,加载界面完成,方法就是我在14楼说的
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
在程序启动阶段,我可以通过在各个资源载入函数之间插入显示进度条的函数来实时显示进度,而在切换画面时,延时主要来自于使用mciSendString函数加载背景音乐,这个函数必须要从外部文件中加载资源,比其内部资源就要慢了不少,但是这个函数是一个整体,没办法拆开来让我在里面插入显示进度条的函数,而且函数异步执行,调用后立即返回。不过我还没有去注意过这个函数是在加载完资源后返回,还是资源未加载完就返回,如果是前者,我可以在调用前进入加载画面,调用完后退出加载画面,这个倒是可以试试。
lpcads 2013-08-07
  • 打赏
  • 举报
回复
其实一般游戏的进度条也都是只分成几段的,每完成一项任务,进度条涨一段,如果分得过细,影响性能不说,编程的时候还特别麻烦麻烦。 如果想让用户看到的进度条“无级增长”,可以用类似动画的技术,在进度条刷新的很短时间内再进一步分段。
lpcads 2013-08-07
  • 打赏
  • 举报
回复
引用 11 楼 wubicheng 的回复:
给 lpcads 的回复: 哦,这样啊,确实说的有道理,不过你说魔兽3进度条只有3段那个是错的,我在配置比较高的电脑上玩时,它的进度条跑得飞快,一下子就满了,而在配置略差些的电脑上玩时,可以很明显的看到进度条是逐渐长满的,如果配置再差些,或者地图再大些,AI或玩家再多些的话,才会是看起来像是只有三段,进一步差的话,进度条又可以发现是一点一点的长满的,只不过长得非常慢。当然我没有故意贬低你电脑配置的意思,请你谅解哈! 我的程序在刚启动时由于大量资源需要载入,延时会比较长,而在切换画面时,更新的资源较少,延时会比较短,如果估秒的话,估短了我担心还没加载完进度条就满了,这个虽然在魔兽中也碰到过这种情况,但是它是如果没有加载完就继续停在加载画面,而我如果无法检测到资源是否已加载完毕的话就没办法实现这一点,用户在加载画面结束后肯定又要继续等待一段时间,这就变相告诉用户这进度条只是给你看看的,并且也容易让用户以为程序卡死了;估长了,我又担心等待时间过长,用户等不下去。所以时间不太好估,毕竟电脑配置不同,加载速度也不同,需要等待的时间也不同,要是配置差别过大,就会暴露出来。
是的,从时间上分段确实不如从函数进度上分段好。 我觉得应该来一门进度条心理学,比如时间短的情况下,比起进度的百分比,用户更关心完成没完成;如果时间很长,用户才会开始关心进度到多少,卡没卡死的问题。
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
给 lpcads 的回复: 哦,这样啊,确实说的有道理,不过你说魔兽3进度条只有3段那个是错的,我在配置比较高的电脑上玩时,它的进度条跑得飞快,一下子就满了,而在配置略差些的电脑上玩时,可以很明显的看到进度条是逐渐长满的,如果配置再差些,或者地图再大些,AI或玩家再多些的话,才会是看起来像是只有三段,进一步差的话,进度条又可以发现是一点一点的长满的,只不过长得非常慢。当然我没有故意贬低你电脑配置的意思,请你谅解哈! 我的程序在刚启动时由于大量资源需要载入,延时会比较长,而在切换画面时,更新的资源较少,延时会比较短,如果估秒的话,估短了我担心还没加载完进度条就满了,这个虽然在魔兽中也碰到过这种情况,但是它是如果没有加载完就继续停在加载画面,而我如果无法检测到资源是否已加载完毕的话就没办法实现这一点,用户在加载画面结束后肯定又要继续等待一段时间,这就变相告诉用户这进度条只是给你看看的,并且也容易让用户以为程序卡死了;估长了,我又担心等待时间过长,用户等不下去。所以时间不太好估,毕竟电脑配置不同,加载速度也不同,需要等待的时间也不同,要是配置差别过大,就会暴露出来。
lpcads 2013-08-07
  • 打赏
  • 举报
回复
引用 9 楼 wubicheng 的回复:
啊~~,那为什么别人可以,我上面说了,那些游戏什么的,它们是怎么做到的,CSDN里没有大神会这个吗?而且我觉得模拟的话还不如没有,你们觉得呢?忽悠人的东西嘛,明明不需要等,你硬要人等那么久,显得自己程序有多么多么的大,这个有点搞假的成分啊。
一般情况下进度条实际上是起示意作用,告诉用户程序没有卡死,一切正常。因而大多数进度条不需要特别准确,意思一下即可。如果lz的延迟时间比较短,几秒的话,进度条分隔成三、四段即可,太细的话反而效率低下。 有两种思路: 1、估计总的秒数t,设个定时器,每 t/3 秒刷新一次。可能最后一段会显得不“均匀”,但实际上无所谓。 2、如果加载的过程是顺序执行一些函数,则可分为3段,其间插入刷新进度条的语句

//begin to load
function1();
SendMessage(hProgress,33,...);
function2();
SendMessage(hProgress,66,...);
function3();
SendMessage(hProgress,100,...);
//loading ends
同样只要大体均匀即可,相信没有用户会无聊到掐秒表的。 PS:玩魔兽3,在加载地图的时候,我就发现进度条好像仅分成三段,在不均匀的三次移动后还要卡一会才进游戏。这么多年来早已习惯,也不觉有什么大不了的。
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
啊~~,那为什么别人可以,我上面说了,那些游戏什么的,它们是怎么做到的,CSDN里没有大神会这个吗?而且我觉得模拟的话还不如没有,你们觉得呢?忽悠人的东西嘛,明明不需要等,你硬要人等那么久,显得自己程序有多么多么的大,这个有点搞假的成分啊。
max_min_ 2013-08-07
  • 打赏
  • 举报
回复
引用 7 楼 wubicheng 的回复:
这样啊,那别人是怎么做到的呢,我们用的很多软件,特别是游戏软件好多都有进度条,而且它们的进度条应该是真实地反映进度,因为电脑慢,进度条长得也慢,电脑快,甚至都看不到进度条增长的画面,而且即使是显示“正在加载”我也需要知道它加载完了没有啊,那么如何知晓资源已经加载完毕呢?
只是下载文件的时候是可以及时获取真实的信息的,我上面已经说了, 把下载好的文件更新程序的这个实时的进度获取不到的,只能模拟了,不是真实值的!
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
这样啊,那别人是怎么做到的呢,我们用的很多软件,特别是游戏软件好多都有进度条,而且它们的进度条应该是真实地反映进度,因为电脑慢,进度条长得也慢,电脑快,甚至都看不到进度条增长的画面,而且即使是显示“正在加载”我也需要知道它加载完了没有啊,那么如何知晓资源已经加载完毕呢?
mujiok2003 2013-08-07
  • 打赏
  • 举报
回复
引用 5 楼 wubicheng 的回复:
给4 楼 mujiok2003 的回复: 这没有多大用处吧,你是假设的总量值为100,并且还假设每隔500毫秒增长总量值的0.05,但是实际情况下,程序运行的时候这些是个未知数吧,要动态测量才可以。这里计算百分比的原理我是懂的,我不知道的是如何去获取资源总量和当前已加载完毕的资源总量。
那是个设计模式的例子而已。 总量和已经完成量很难估算的时候, 显示“正在加载”就好了。
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
给4 楼 mujiok2003 的回复: 这没有多大用处吧,你是假设的总量值为100,并且还假设每隔500毫秒增长总量值的0.05,但是实际情况下,程序运行的时候这些是个未知数吧,要动态测量才可以。这里计算百分比的原理我是懂的,我不知道的是如何去获取资源总量和当前已加载完毕的资源总量。
mujiok2003 2013-08-07
  • 打赏
  • 举报
回复

//demo for observer pattern
#include <iostream>
#include <Windows.h>

struct Worker;

struct UI
{
   void reg(Worker* worker)
   {
	   worker_ = worker;
   }
   virtual void Notify();
private:
   Worker* worker_;
};

struct Worker
{
	Worker()
		: total_(100), finished_(0)
	{

	}
	virtual void update(double& total, double& finished)
	{
		total = total_;
		finished = finished_;
	}
	
	void working(UI* ui_)
	{
		while(finished_ < total_)
		{
		    finished_ += total_ * 0.05;
			ui_->Notify();
			Sleep(500);
		}
		std::cerr << std::endl;
	}
private:
	double total_, finished_;	
};


void UI::Notify()
{
	double t, f;
	worker_->update(t,f);
	std::cerr << "\b\b\b\b=== " << (int)(f / t * 100) << "%";
}


int main(int argc, char* argv[])
{
	UI ui;
	Worker worker;
	ui.reg(&worker);
	worker.working(&ui);
	
	return 0;
}
wubicheng 2013-08-07
  • 打赏
  • 举报
回复
引用 1 楼 max_min_ 的回复:
之前做过客户端升级设备的进度条的显示问题 首先获取总共学要加载的文件信息以及大小, 接收的时候,实时的接收大小/文件大小,来实时的显示已经下载的文件大小 开始升级的时候,写入的时候,这个无法获取实时,所以这个是开个线程模拟的进度了, 当升级完成就会返回全部升级完成,
文件的大小就是所占内存对吧,如何获取已经加载的文件大小和总共需要加载的文件大小呢?这么说的话虽然思路清晰了些,但是具体还是不知道该如何做,可以说几个相关的API函数给我吗,能够说明用法更好,我自己找用法也可以,但是我要先知道个函数名才好找。
引用 2 楼 zhao4zhong1 的回复:
进度每隔比如1秒进多少可以是一个动态调整的步进值。 开始时(0%到5%)可以选一个固定进度步进值,边前进边重新估算下一步的步进值,通常到20%以后,这个步进值就比较接近实际值了。
这个怎么个动态调整法呢?我根据什么来进行动态调整,是跟1楼说的一样么?那样的话我觉得只要能够获取当前已加载的文件大小和总共需要加载的文件大小,然后计算百分比就可以实时显示了,关键是这个步进值我该如何去估算呢?如果随意取值,那依然是无法反映真实的进度。希望你能够再说详细一些。
赵4老师 2013-08-07
  • 打赏
  • 举报
回复
进度每隔比如1秒进多少可以是一个动态调整的步进值。 开始时(0%到5%)可以选一个固定进度步进值,边前进边重新估算下一步的步进值,通常到20%以后,这个步进值就比较接近实际值了。
max_min_ 2013-08-07
  • 打赏
  • 举报
回复
之前做过客户端升级设备的进度条的显示问题 首先获取总共学要加载的文件信息以及大小, 接收的时候,实时的接收大小/文件大小,来实时的显示已经下载的文件大小 开始升级的时候,写入的时候,这个无法获取实时,所以这个是开个线程模拟的进度了, 当升级完成就会返回全部升级完成,

33,311

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 新手乐园
社区管理员
  • 新手乐园社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧