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


场景:

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


原文地址:https://www.cnblogs.com/mengfanrong/p/5042319.html