C++ GUI库FLTK学习心得(一)
最近一直想接触一些新东西,包括新技术,还有新的学习方法。之前自己几乎没有接触过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空间被用户或其它程序关闭。