FLTK学习笔记2-回调函数

FLTK学习笔记2-回调函数

回调函数

回调函数(Callback)简单说来就是一个以函数指针的方式被调用的函数。

考虑如下情况,我们编写了一个整数排序算法函数mySort

void mySort(std::vector<int>& v);

这个函数能够让vector里面的数由小到大排列。但是我们希望这个函数能够支持一些其它规则,例如让数字按绝对值由小到大排列,因此我们可以编写以下函数:

void mySort(std::vector<int>& v, bool (*pFun)(int, int));
bool smaller(int i1, int i2);
bool smallerAbs(int i1, int i2);

其中bool (*pFun)(int, int))是一个指向返回值bool,参数为两个int的函数指针,smallersmallerAbs分别是两种排序规则的实现函数,于是mySort函数就可以用以下方式在两种规则之间进行切换:

mySort(v, smaller);			/* 用smaller规则排序 */
mySort(v, smallerAbs);		/* 用smallerAbs规则排序 */

为控件添加回调函数

FLTK中通过回调函数来响应控件的事件(比如按钮被点击)。

FLTK中的回调函数的定义如以下形式:

void widget_cb(Fl_Widget* pw, void* pv);

其返回类型为void,参数有两个,一个是指向Fl_Widget类型的指针pw,另一个是指向void类型的指针pv。

类型Fl_Widget是所有控件类型的基类,pw实际上是指向调用回调函数的控件。例如,一个按钮pButton1被点击后调用回调函数button1_cb,其回调函数的第一个参数pw就是指向pButton1的指针。

第二个参数pv是要传给回调函数的额外数据。例如,要实现一个点击后改变另一个控件pBox上文字的按钮pButton1,可以在定义回调函数时将指向控件pBox的指针作为第二个参数。

代码示例:

void button1_cb(Fl_Widget* w, void* p){
    
    
    Fl_Button* o1 = (Fl_Button*)w;						/* 将Fl_Widget*类型转换为Fl_Button*类型,以调用value方法 */
    o1->value(o1->value()?0:1);
    w->label(o1->value()?"按钮1的值为1":"按钮1的值为0");
    Fl_Box* o2 = (Fl_Box*)p;							/* 将void*类型转换为Fl_Box类型以调用label方法 */
    o2->label("按钮1被点击");
}

pButton1->callback(button1_cb, (void*)pBox);

在FLTK中,一种方法往往有两种重载:一种是带参数的,其作用是设置变量的值,例如value(1)Fl_Button中私有变量value_的值设为1;另一种是没有参数的,其作用是获取变量的值,例如value()将返回私有变量value_的值。其函数原型如下:

int value(int v);
char value() const {
    
    return value_;}

回调函数的注意要点

  • 类内定义回调方法时要将回调函数设为静态方法,否则会编译报错。具体解释见这里
  • 在回调函数中要将传入参数进行类型转换以调用其具体控件相关的方法

程序示例

下面程序创建了一个标签以及三个按钮,前两个按钮点击后将会改变自身文字以及标签上的文字,第三个按钮点击后退出程序。

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Box.H>

void button1_cb(Fl_Widget* w, void* p){
    
    
    Fl_Button* o1 = (Fl_Button*)w;
    o1->value(o1->value()?0:1);
    w->label(o1->value()?"按钮1的值为1":"按钮1的值为0");
    Fl_Box* o2 = (Fl_Box*)p;
    o2->label("按钮1被点击");
}
void button2_cb(Fl_Widget* w, void* p){
    
    
    Fl_Button* o1 = (Fl_Button*)w;
    o1->value(o1->value()?0:1);
    w->label(o1->value()?"按钮2的值为1":"按钮2的值为0");
    Fl_Box* o2 = (Fl_Box*)p;
    o2->label("按钮2被点击");
}
void quit_cb(Fl_Widget* w, void* p){
    
    
    exit(0);
}

int main(){
    
    
    Fl_Double_Window window(390, 180, "回调函数");
    Fl_Box* pBox = new Fl_Box(50, 50, 290, 50, "没有按钮被点击");
    Fl_Button* pButton1 = new Fl_Button(50, 120, 100, 30, "按钮1");
    Fl_Button* pButton2 = new Fl_Button(170, 120, 100, 30, "按钮2");
    Fl_Button* pQuitButton = new Fl_Button(290, 120, 50, 30, "退出");

    pButton1->callback(button1_cb, (void*)pBox);
    pButton2->callback(button2_cb, (void*)pBox);
    pQuitButton->callback(quit_cb, nullptr);
    
    window.end();
    window.show();
    return Fl::run();
}

这里注意在编译的时候记得加上-lfltk命令(在MSYS2上还要加上-mwindows -DWIN32 -lole32 -luuid -lcomctl32)。

运行结果:
回调函数

相关链接:
专栏:FLTK
FLTK学习笔记1-绘制基本控件(按钮、文本输入、容器)
FLTK学习笔记3-随机点名器

猜你喜欢

转载自blog.csdn.net/willian113/article/details/106728387