[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