最近一直想接觸一些新東西,包括新技術,還有新的學習方法。之前自己幾乎沒有接觸過GUI編程(除了曾經用過Win32API畫出一個最簡單的窗口)。后來無意間翻到過C++之父Bjarne Stroustrup的新書《Programming: Principles and Practice using C++》,這本書的用意是帶領沒有豐富編程經驗的人入門,並沒有涉及到過多C++的技術細節,更多地是從程序開發的角度來切入,當然,示例本身是用C++來寫的(好歹人家是是C++之父嘛~)。
里面專門有一部分介紹GUI,BS采用了FLTK庫做了例子,自己做了一些很少的封裝,並以此來帶領大家入門,內容十分詳實,也激發了我學習GUI的興趣。我想,既然我正在學習C++,為何不通過C++圖形庫來學習呢?這樣一方面可以可以讓我學習到具體編程中如何進行類的設計,另一方面可以讓我了解GUI編程的一些知識。好主意!
之前有一篇文章介紹(轉載)了8個免費C++ GUI庫,我做了一個大體的比較,感覺FLTK更適合我的學習,原因如下:
1、例子很豐富
FLTK提供了很多可執行的例子,在Visual C++ 2010 Express中可以直接編譯運行。下圖是一個Demo的入口,點擊里面的按鈕可以選擇各種例子,非常豐富:
2、文檔很全
在FLTK Programming Mannual中,對FLTK的介紹非常到位,不僅介紹了常用的組件,還通過一個簡單的文本編輯器的例子教讀者怎么去運用,非常好!
3、FLTK的開發很活躍
從圖中可以看出,現在FLTK有三個大版本,其中穩定版是v1.3.2,而v1.3.x、v2.0.x和v.3.0.x都在開發中,比較有前途。
3、FLTK提供的例子有我想要的效果
我想做一個左邊是Tree,右邊是Table的界面,而例子中正巧有這個,可以直接參考,節省時間。
4、C++之父用的東西,肯定不會太爛
OK,既然選好了,就開始學吧,從官方文檔開始看。
首先,寫第一個FLTK程序。所有的程序都應該包含頭文件<FL/Fl.H>,如果程序中使用到其它組件的話,也要包含對應的頭文件。頭文件的命名其實很有規律,不具體介紹了。
第一個例子:
#include <FL/Fl.H> #include <FL/Fl_Window.H> #include <FL/Fl_Box.H> int main(int argc, char **argv) { Fl_Window *window = new Fl_Window(340,180); Fl_Box *box = new Fl_Box(20,40,300,100,"Hello, World!"); box->box(FL_UP_BOX); box->labelfont(FL_BOLD+FL_ITALIC); box->labelsize(36); box->labeltype(FL_SHADOW_LABEL); window->end(); window->show(argc, argv); return Fl::run(); }
程序首先創建了一個窗口(Fl_Window)對象,所有接下來的組件都會自動成為它的子組件。
Fl_Window *window = new Fl_Window(340,180);
然后,創建一個包含“Hello, World!”字符串的顯示框,這個顯示框自動被加到window中。
Fl_Box *box = new Fl_Box(20,40,300,100,"Hello, World!");
接着,設置顯示框的類型以及標簽的字體、大小和風格:
box->box(FL_UP_BOX); box->labelfont(FL_BOLD+FL_ITALIC); box->labelsize(36); box->labeltype(FL_SHADOW_LABEL);
然后,我們告訴FLTK不要再往window中加更多組件了:
window->end();
最后,顯示窗口,並進入FLTK事件循環:
window->show(argc, argv); return Fl::run();
程序顯示如下:
可以通過Esc退出程序。
總結一下FLTK的一些基本知識:
1、組件通過new創建,多數組件的構造函數類似於:
Fl_Widget(x, y, width, height, label)
其中x和y為窗口或組件的左上角在屏幕上的坐標,width和height為窗口或組件的長寬,label是指向要顯示的字符串的指針(默認為NULL)。
2、組件層次
FLTK中添加組件很容易,可以在myGroup->begin()和myGroup->end()中間來添加。
3、Get/Set方法和jQuery的風格一致
4、改變組件屬性以后需要調用redraw(),value()和label()例外
5、FLTK程序必須周期性地檢查Fl::check(),或者等待Fl::wait(),或者調用Fl::run()方法進入標准事件處理循環。調用Fl::run()等價於while(Fl::wait());,Fl::run()一直運行直到FLTK空間被用戶或其它程序關閉。