[wxWidgets]_[初级]_[常见更新进度条的方案]

场景:

1. 很多程序需要根据处理业务的进度来更新进度条,进度条的目的是让用户能知道业务处理的进度,有进度条的程序更友好,让用户知道程序在运行,而不是没有响应。

2. 现在更新进度条的见过两种方法,一种是通过事件(信号,队列)的发送让主线程按照发送的顺序来更新进度条,一种是设置一个全局整形变量,

通过运行定时器的方式来更新进度条。第一种不适合在更新频率比较高的地方,比如一秒钟发送了20个事件,这样会造成主线程忙于处理事件界面出现假死状态。

所以最好的办法就是使用第2种通过定时器更新进度条,设置一个合理的值,比如500毫秒这样既能看到更新的进度,也不会让主线程过于忙。

3. 这里用wxWidgets做例子,其实mfc,wtl,cocoa都是一样的。

部分代码:

my_thread.cpp

#include "domain/my_thread.h"
#include "window/my_frame.h"

wxThread::ExitCode MyThread::Entry()
{
	Sleep(500);
	int i = 1;
	while (!TestDestroy() && i <= 100)
	{
		if(type_)
		{
			//第一种方法,发事件更新进度条,注意,不能直接更新进度条控件,因为非主线程不能更新控件
			wxCommandEvent* evt = new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_UPDATE);
			evt->SetInt(i);
			wxQueueEvent(m_pHandler->GetEventHandler(), evt);
		}else
		{
			//第二种方法,直接更新MyFrame里的Int成员变量,然会wxTimer会根据这个值自动更新进度条控件.
			m_pHandler->progress_value_ = i;
			Sleep(200);
		}
		++i;
	}
	//1.最后这个其实还是必要的,告诉wxTimer可以结束了。总之就是通知界面工作任务已经完成,你自己做该做的事。
	wxQueueEvent(m_pHandler->GetEventHandler(), new wxCommandEvent(wxEVT_COMMAND_MYTHREAD_COMPLETED));
	return (wxThread::ExitCode)0;
}

my_frame.cpp

#include "window/my_frame.h"
#include "wx/xrc/xmlres.h"
#include <iostream>
#include "domain/my_thread.h"

using namespace std;

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
	EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
	EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_COMPLETED,	MyFrame::OnThreadCompletion)
	EVT_TIMER(wxID_ANY,MyFrame::OnTimer)
END_EVENT_TABLE()

wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);

void MyFrame::Init()
{
   gauge_ =  XRCCTRL(*this, "m_gauge1", wxGauge);

   event_update_button_ = XRCCTRL(*this, "m_button1", wxButton);
   event_update_button_->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
        wxCommandEventHandler(MyFrame::OnEventUpdate), this, XRCID("m_button1"));
   timer_update_button_ = XRCCTRL(*this, "m_button3", wxButton);
   timer_update_button_->Bind(wxEVT_COMMAND_BUTTON_CLICKED,
        wxCommandEventHandler(MyFrame::OnTimerUpdate), this, XRCID("m_button3"));

   timer.SetOwner(this->GetEventHandler());
}

MyFrame::MyFrame(wxWindow* parent)
{
	progress_value_ = 0;
}

MyFrame::~MyFrame()
{
}

void MyFrame::OnThreadUpdate(wxCommandEvent& evt)
{
	cout << "OnThreadUpdate" << endl;
	gauge_->SetValue(evt.GetInt());
}

void MyFrame::OnThreadCompletion(wxCommandEvent&)
{
	cout << "OnThreadCompletion" << endl;
	if(!type_)
	{
		timer.Stop();
		gauge_->SetValue(progress_value_);
	}

	timer_update_button_->Enable();
	event_update_button_->Enable();

}

void MyFrame::OnTimer(wxTimerEvent&)
{
	cout << "OnTimer" << endl;
	gauge_->SetValue(progress_value_);
}

void MyFrame::DoTask(bool type)
{
	timer_update_button_->Enable(false);
	event_update_button_->Enable(false);

    MyThread *m_pThread = new MyThread(type,this);
	if ( m_pThread->Run() != wxTHREAD_NO_ERROR )
	{
		cout << "Can't create the thread!: " << type << endl;
		delete m_pThread;
		m_pThread = NULL;
	}
}

void MyFrame::OnTimerUpdate(wxCommandEvent& evt)
{
	cout << "OnTimerUpdate" << endl;
	gauge_->SetValue(0);
	progress_value_ = 0;
	type_ = false;
	timer.Start(500);
	DoTask(type_);
}

void MyFrame::OnEventUpdate(wxCommandEvent& evt)
{
    cout << "OnEventUpdate" << endl;
	gauge_->SetValue(0);
	progress_value_ = 0;
	type_ = true;
	DoTask(type_);
}

gui.cpp

#include "wx/wxprec.h"

#ifndef WX_PRECOMP
    #include "wx/wx.h"
#endif

#include "wx/xrc/xmlres.h"
#include <assert.h>
#include <iostream>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include "wx/listctrl.h"
#include "wx/grid.h"
#include "wx/event.h"

#include "window/my_frame.h"

using namespace std;

static void OpenConsole()
{
	AllocConsole();
	HANDLE   handle   =   GetStdHandle(STD_OUTPUT_HANDLE);
	int   hCrt   =   _open_osfhandle((long)handle,_O_TEXT);
	FILE   *   hf   =   _fdopen(   hCrt,   "w"   );
	*stdout   =   *hf;
}

static wxString GetAppRunDirectory()
{
    wxString directory(wxTheApp->argv[0]);
    directory.Replace(wxT("\\"), wxT("/"));
    wxString str = directory.BeforeLast('/');
    if(str.IsEmpty())
    {
      return wxT(".");
    }
    return directory.BeforeLast('/');
}

static wxString GetInstallDirectory()
{
	wxString directory = GetAppRunDirectory();
#ifdef __QXWIN32__
    return directory.BeforeLast('/');
#else
    return directory;
#endif
}

class MyApp : public wxApp
{
public:
    virtual bool OnInit();
    virtual int OnExit();
};

IMPLEMENT_APP(MyApp)

// 'Main program' equivalent: the program execution "starts" here
bool MyApp::OnInit()
{
  if (!wxApp::OnInit())
  {
	return false;
  }
  OpenConsole();
  wxInitAllImageHandlers();
  wxXmlResource::Get()->InitAllHandlers();

  wxString ui_dir = GetInstallDirectory()+wxT("/Themes");
  wxXmlResource::Get()->LoadAllFiles(ui_dir);

  MyFrame *frame = new MyFrame(NULL);
  bool loaded = wxXmlResource::Get()->LoadFrame(frame, NULL, "MyFrame1");
  assert(loaded);
  frame->Init();
  frame->Show(true);

  return true;
}

int MyApp::OnExit()
{
	return 0;
}

截图:

完整代码下载地址:

http://download.csdn.net/detail/infoworld/8105011

时间: 2024-11-10 10:20:08

[wxWidgets]_[初级]_[常见更新进度条的方案]的相关文章

[wxWidgets]_[0基础]_[经常更新进度条程序]

场景: 1. 非常根据程序的进展需要处理业务,以更新进度条,进度条的目的是为了让用户知道业务流程的进度.一个进度条程序更友好,让用户知道在程序执行.不是没有反应. 2. 现在更新见过这两种方法的进展.事件(信号,队列)的发送让主线程依照发送的顺序来更新进度条,一种是设置一个全局整形变量, 通过执行定时器的方式来更新进度条.第一种不适合在更新频率比較高的地方,比方一秒钟发送了20个事件,这样会造成主线程忙于处理事件界面出现假死状态. 所以最好的办法就是使用第2种通过定时器更新进度条,设置一个合理的

android一个上传图片的例子,包括如何终止上传过程,如果在上传的时候更新进度条(一)

先上效果图: Layout为: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent&quo

ios线程练习更新进度条

类似于,我们加载网页时候的进度条,我们来看看它们是怎么工作的. #import "ViewController.h" @interface ViewController () { UIProgressView *_view; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置进度条 _view = [[UIProgressView alloc]init]; _view

C# 模式窗口下更新进度条

public partial class frmProcessBar : Form { public frmProcessBar() { InitializeComponent(); } public bool Increase(int nValue) { if (nValue > 0) { if (progressBar1.Value + nValue < progressBar1.Maximum) { progressBar1.Value += nValue; return true; }

WPF BackGroundWord 异步加载更新进度条示例

1 <Window x:Class="AsynchronousLoading.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/e

BootStrap学习(4)_分页&amp;标签&amp;缩略图&amp;警告&amp;进度条

一.分页 分页(Pagination),是一种无序列表,Bootstrap 像处理其他界面元素一样处理分页.  .pagination     --添加该 class 来在页面上显示分页. .disabled         --定义不可点击的链接 .active             --指示当前页面 .pagination-lg, .pagination-sm   --标签大小 .pager         --翻页 1.分页 <!DOCTYPE html> <html xmlns

步步为营_Android开发课[23]_用户界面之ProgressBar(进度条)

Focus on technology, enjoy life!-- QQ:804212028 浏览链接:http://blog.csdn.net/y18334702058/article/details/44624305 主题:用户界面之ProgressBar(进度条) - 自定义ProgressBar进度条(实例): activity_main.xml: <?xml version="1.0" encoding="utf-8"?> <Linea

JS框架_(Progress.js)圆形动画进度条

圆形动画进度条效果: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <style> p { position: fixed; top: 50%; left: 0; right: 0; text-align: center; transf

JS框架_(JQuery.js)纯css3进度条动画

进度条动画效果: <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="viewport" content="w