在用CCD相機拍照的圖像進行實時成像的時候遇到這麼一個問題:
1: RunCamera();
2: while (1) {
3: GetImg();
4: ShowImg();
5: }
6: CloseCamera();
想要對獲取的圖像進行實時成像,最先想到的是采用while(1)的方式,但是這樣的方式會帶來一些問題,除了終止程序,沒有辦法使得循環停下,這個結果不是我們想要的。如果加上一個i < 100類似的條件,數量太大需要等,數量太小很快就結束了。我們想要設計的是能夠隨叫隨停的,能夠控制成像與停止的功能。
第一個想到的是onTimer的方式進行實現,不過水平低低,還是先在網上搜索一翻吧,功夫不負有心人,還是找到了。Making a render loop。
它采用了兩種方式,一種為事件處理方式,一種為剛想到的onTimer的方式。下面參考上述鏈接中的內容,同時考慮自己的功能需求,給出了自己實現的具體代碼。
所有的代碼都是在codeblock下實現的。
1. 事件處理方式
采用onIdel的方式,一種頻率最快的方式之一;但是頻率不是固定的,當你進行其它操作時,如打開菜單Idel將會停止處理。
1: // the most improtant code in frame.h and frame.cpp
2: /***************************************************************
3: * Name: tmp1Main.h
4: * Purpose: Defines Application Frame
5: * Author: grass in moon
6: * Created: 2012-07-06
7: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
8: * License:
9: **************************************************************/
10:
11: #ifndef TMP1MAIN_H
12: #define TMP1MAIN_H
13:
14: #ifndef WX_PRECOMP
15: #include <wx/wx.h>
16: #endif
17:
18: #include "tmp1App.h"
19:
20: class tmp1Frame: public wxFrame
21: {
22: public:
23: tmp1Frame(wxFrame *frame, const wxString& title);
24: ~tmp1Frame();
25:
26: // for painting
27: void PaintNow();
28: void render(wxDC& dc);
29:
30: private:
31: enum
32: {
33: idMenuQuit = 1000,
34: idMenuAbout,
35: idStartLoop,
36: idStopLoop
37: };
38:
39: // mark loop on or off
40: bool render_loop_on;
41:
42: void OnClose(wxCloseEvent& event);
43: void OnQuit(wxCommandEvent& event);
44: void OnAbout(wxCommandEvent& event);
45: void OnStartLoop(wxCommandEvent& event);
46: void OnStopLoop(wxCommandEvent& event);
47:
48: // deel with wxIdleEvent
49: void OnIdle(wxIdleEvent& event);
50:
51: DECLARE_EVENT_TABLE()
52: };
53:
54:
55: #endif // TMP1MAIN_H
56:
57: /***************************************************************
58: * Name: tmp1Main.cpp
59: * Purpose: Code for Application Frame
60: * Author: grass in moon
61: * Created: 2012-07-06
62: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
63: * License:
64: **************************************************************/
65:
66: #ifdef WX_PRECOMP
67: #include "wx_pch.h"
68: #endif
69:
70: #ifdef __BORLANDC__
71: #pragma hdrstop
72: #endif //__BORLANDC__
73:
74: #include "tmp1Main.h"
75:
76: //helper functions
77: enum wxbuildinfoformat
78: {
79: short_f, long_f
80: };
81:
82: wxString wxbuildinfo(wxbuildinfoformat format)
83: {
84: wxString wxbuild(wxVERSION_STRING);
85:
86: if (format == long_f )
87: {
88: #if defined(__WXMSW__)
89: wxbuild << _T("-Windows");
90: #elif defined(__WXMAC__)
91: wxbuild << _T("-Mac");
92: #elif defined(__UNIX__)
93: wxbuild << _T("-Linux");
94: #endif
95:
96: #if wxUSE_UNICODE
97: wxbuild << _T("-Unicode build");
98: #else
99: wxbuild << _T("-ANSI build");
100: #endif // wxUSE_UNICODE
101: }
102:
103: return wxbuild;
104: }
105:
106: BEGIN_EVENT_TABLE(tmp1Frame, wxFrame)
107: EVT_CLOSE(tmp1Frame::OnClose)
108: EVT_MENU(idMenuQuit, tmp1Frame::OnQuit)
109: EVT_MENU(idMenuAbout, tmp1Frame::OnAbout)
110: EVT_MENU(idStartLoop, tmp1Frame::OnStartLoop)
111: EVT_MENU(idStopLoop, tmp1Frame::OnStopLoop)
112: EVT_IDLE(tmp1Frame::OnIdle)
113: END_EVENT_TABLE()
114:
115: tmp1Frame::tmp1Frame(wxFrame *frame, const wxString& title)
116: : wxFrame(frame, -1, title)
117: {
118: #if wxUSE_MENUS
119: // create a menu bar
120: wxMenuBar* mbar = new wxMenuBar();
121: wxMenu* fileMenu = new wxMenu(_T(""));
122: fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application"));
123: fileMenu->Append(idStartLoop, _("St&artLoop")); // for starting draw text
124: fileMenu->Append(idStopLoop, _("Sto&pLoop")); // for stoping draw text
125: mbar->Append(fileMenu, _("&File"));
126:
127: wxMenu* helpMenu = new wxMenu(_T(""));
128: helpMenu->Append(idMenuAbout, _("&About\tF1"), _("Show info about this application"));
129: mbar->Append(helpMenu, _("&Help"));
130:
131: SetMenuBar(mbar);
132: #endif // wxUSE_MENUS
133:
134: #if wxUSE_STATUSBAR
135: // create a status bar with some information about the used wxWidgets version
136: CreateStatusBar(2);
137: SetStatusText(_("Hello Code::Blocks user!"),0);
138: SetStatusText(wxbuildinfo(short_f), 1);
139: #endif // wxUSE_STATUSBAR
140:
141: render_loop_on = false;
142: }
143:
144:
145: tmp1Frame::~tmp1Frame()
146: {
147: }
148:
149: void tmp1Frame::OnClose(wxCloseEvent &event)
150: {
151: Destroy();
152: }
153:
154: void tmp1Frame::OnQuit(wxCommandEvent &event)
155: {
156: Destroy();
157: }
158:
159: void tmp1Frame::OnAbout(wxCommandEvent &event)
160: {
161: wxString msg = wxbuildinfo(long_f);
162: wxMessageBox(msg, _("Welcome to..."));
163: }
164:
165: // set render_loop_on true, make OnIdle can draw text
166: void tmp1Frame::OnStartLoop(wxCommandEvent& event)
167: {
168: render_loop_on = true;
169: }
170:
171: // set render_loop_on true, make OnIdle can skip draw text
172: void tmp1Frame::OnStopLoop(wxCommandEvent& event)
173: {
174: render_loop_on = false;
175: }
176:
177: // paint depend on render_loop_on is true or off
178: void tmp1Frame::OnIdle(wxIdleEvent& event)
179: {
180: if (render_loop_on)
181: {
182: PaintNow();
183: event.RequestMore();
184: }
185: }
186:
187: void tmp1Frame::PaintNow()
188: {
189: wxClientDC dc(this);
190: render(dc);
191: }
192:
193: // draw text on screen
194: void tmp1Frame::render(wxDC& dc)
195: {
196: static int y = 0;
197: static int y_speed = 2;
198:
199: y += y_speed;
200: if (y < 0) y_speed = 2;
201: if (y > 200) y_speed = -2;
202:
203: dc.SetBackground(*wxWHITE_BRUSH);
204: dc.Clear();
205: dc.DrawText(wxT("Testing"),40,y);
206: }
207:
2. 時間處理方式
采用onTimer,具有較為固定的處理頻率,當處理其他操作如打開菜單式,並不會中止;速度不像事件處理方式那麼快,實現的速率與操作系統相關。
目前知道的wxTimer實現的方式有兩種,1. 采用EVT_TIMER事件處理方式(該處理方法已經在文簡易定時器設計中實現) 2. 創建一個wxTimer的子類,然後對wxTimer中的Notify函數進行重載。
下面采用第二種方式,進行實現。
tmp1Main.h
1: /***************************************************************
2: * Name: tmp1Main.h
3: * Purpose: Defines Application Frame
4: * Author: grass in moon
5: * Created: 2012-07-06
6: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
7: * License:
8: **************************************************************/
9:
10: #ifndef TMP1MAIN_H
11: #define TMP1MAIN_H
12:
13: #ifndef WX_PRECOMP
14: #include <wx/wx.h>
15: #endif
16:
17: #include "tmp1App.h"
18:
19: class RenderTimer; // make renderTimer.h not influence this file compling time
20:
21: class tmp1Frame: public wxFrame
22: {
23: public:
24: tmp1Frame(wxFrame *frame, const wxString& title);
25: ~tmp1Frame();
26:
27: // for painting
28: void PaintNow();
29: void render(wxDC& dc);
30:
31: private:
32: // derived from wxTimer
33: RenderTimer* timer;
34:
35: enum
36: {
37: idMenuQuit = 1000,
38: idMenuAbout,
39: idStartLoop,
40: idStopLoop
41: };
42:
43: void OnClose(wxCloseEvent& event);
44: void OnQuit(wxCommandEvent& event);
45: void OnAbout(wxCommandEvent& event);
46: void OnStartLoop(wxCommandEvent& event);
47: void OnStopLoop(wxCommandEvent& event);
48:
49: DECLARE_EVENT_TABLE()
50: };
51:
52: #endif // TMP1MAIN_H
tmp1Main.cpp
1: /***************************************************************
2: * Name: tmp1Main.cpp
3: * Purpose: Code for Application Frame
4: * Author: grass in moon
5: * Created: 2012-07-06
6: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
7: * License:
8: **************************************************************/
9:
10: #ifdef WX_PRECOMP
11: #include "wx_pch.h"
12: #endif
13:
14: #ifdef __BORLANDC__
15: #pragma hdrstop
16: #endif //__BORLANDC__
17:
18: #include "tmp1Main.h"
19: #include "renderTimer.h"
20:
21: //helper functions
22: enum wxbuildinfoformat
23: {
24: short_f, long_f
25: };
26:
27: wxString wxbuildinfo(wxbuildinfoformat format)
28: {
29: wxString wxbuild(wxVERSION_STRING);
30:
31: if (format == long_f )
32: {
33: #if defined(__WXMSW__)
34: wxbuild << _T("-Windows");
35: #elif defined(__WXMAC__)
36: wxbuild << _T("-Mac");
37: #elif defined(__UNIX__)
38: wxbuild << _T("-Linux");
39: #endif
40:
41: #if wxUSE_UNICODE
42: wxbuild << _T("-Unicode build");
43: #else
44: wxbuild << _T("-ANSI build");
45: #endif // wxUSE_UNICODE
46: }
47:
48: return wxbuild;
49: }
50:
51: BEGIN_EVENT_TABLE(tmp1Frame, wxFrame)
52: EVT_CLOSE(tmp1Frame::OnClose)
53: EVT_MENU(idMenuQuit, tmp1Frame::OnQuit)
54: EVT_MENU(idMenuAbout, tmp1Frame::OnAbout)
55: EVT_MENU(idStartLoop, tmp1Frame::OnStartLoop)
56: EVT_MENU(idStopLoop, tmp1Frame::OnStopLoop)
57: END_EVENT_TABLE()
58:
59: tmp1Frame::tmp1Frame(wxFrame *frame, const wxString& title)
60: : wxFrame(frame, -1, title)
61: {
62: #if wxUSE_MENUS
63: // create a menu bar
64: wxMenuBar* mbar = new wxMenuBar();
65: wxMenu* fileMenu = new wxMenu(_T(""));
66: fileMenu->Append(idMenuQuit, _("&Quit\tAlt-F4"), _("Quit the application"));
67: fileMenu->Append(idStartLoop, _("St&artLoop")); // for starting draw text
68: fileMenu->Append(idStopLoop, _("Sto&pLoop")); // for stoping draw text
69: mbar->Append(fileMenu, _("&File"));
70:
71: wxMenu* helpMenu = new wxMenu(_T(""));
72: helpMenu->Append(idMenuAbout, _("&About\tF1"), _("Show info about this application"));
73: mbar->Append(helpMenu, _("&Help"));
74:
75: SetMenuBar(mbar);
76: #endif // wxUSE_MENUS
77:
78: #if wxUSE_STATUSBAR
79: // create a status bar with some information about the used wxWidgets version
80: CreateStatusBar(2);
81: SetStatusText(_("Hello Code::Blocks user!"),0);
82: SetStatusText(wxbuildinfo(short_f), 1);
83: #endif // wxUSE_STATUSBAR
84:
85: timer = new RenderTimer(this);
86: }
87:
88:
89: tmp1Frame::~tmp1Frame()
90: {
91: delete timer;
92: }
93:
94: void tmp1Frame::OnClose(wxCloseEvent &event)
95: {
96: Destroy();
97: }
98:
99: void tmp1Frame::OnQuit(wxCommandEvent &event)
100: {
101: Destroy();
102: }
103:
104: void tmp1Frame::OnAbout(wxCommandEvent &event)
105: {
106: wxString msg = wxbuildinfo(long_f);
107: wxMessageBox(msg, _("Welcome to..."));
108: }
109:
110: // set render_loop_on true, make OnIdle can draw text
111: void tmp1Frame::OnStartLoop(wxCommandEvent& event)
112: {
113: timer->StartLoop();
114: }
115:
116: // set render_loop_on true, make OnIdle can skip draw text
117: void tmp1Frame::OnStopLoop(wxCommandEvent& event)
118: {
119: timer->StopLoop();
120: }
121:
122: void tmp1Frame::PaintNow()
123: {
124: wxClientDC dc(this);
125: render(dc);
126: }
127:
128: // draw text on screen
129: void tmp1Frame::render(wxDC& dc)
130: {
131: static int y = 0;
132: static int y_speed = 2;
133:
134: y += y_speed;
135: if (y < 0) y_speed = 2;
136: if (y > 200) y_speed = -2;
137:
138: dc.SetBackground(*wxWHITE_BRUSH);
139: dc.Clear();
140: dc.DrawText(wxT("Testing"),40,y);
141: }
renderTimer.h
1: /***************************************************************
2: * Name: renderTimer.h
3: * Purpose: used for onTimer
4: * Author: grass in moon
5: * Created: 2012-07-06
6: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
7: * License:
8: **************************************************************/
9:
10: #ifndef RENDERTIMER_H_INCLUDED
11: #define RENDERTIMER_H_INCLUDED
12:
13: class tmp1Frame;
14:
15: class RenderTimer : public wxTimer
16: {
17: tmp1Frame* tmpFrame;
18: public:
19: RenderTimer(tmp1Frame* tmpFrame);
20: void Notify();
21: void StartLoop();
22: void StopLoop();
23: };
24:
25: #endif // RENDERTIMER_H_INCLUDED
renderTimer.cpp
1: /***************************************************************
2: * Name: renderTimer.cpp
3: * Purpose: used for onTimer
4: * Author: grass in moon
5: * Created: 2012-07-06
6: * Copyright: grass in moon (http://www.cppblog.com/grass-and-moon/)
7: * License:
8: **************************************************************/
9: #include "tmp1Main.h"
10: #include "renderTimer.h"
11:
12: RenderTimer::RenderTimer(tmp1Frame* tmpFrame)
13: {
14: this->tmpFrame = tmpFrame;
15: }
16:
17: // perform the draw text action
18: void RenderTimer::Notify()
19: {
20: tmpFrame->PaintNow();
21: }
22:
23: // set the interval time is 10 ms
24: void RenderTimer::StartLoop()
25: {
26: wxTimer::Start(10);
27: }
28:
29: void RenderTimer::StopLoop()
30: {
31: wxTimer::Stop();
32: }