1.回调函数讲解
我们绕点远路来回答这个问题。
编程分为两类:系统编程(system programming)和应用编程(application programming)。
- 所谓系统编程,简单来说,就是编写库
- 而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。
系统程序员会给自己写的库留下一些接口,即API(应用编程接口),以供应用程序员使用。
所以在抽象层的图示里,库位于应用的底下。当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。
但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。
这个被传入的、后又被调用的函数就称为回调函数(callback function)。
打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。
这里,“叫醒”这个行为是旅馆提供的,相当于库函数
但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数
而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数
如下图所示(图片来源:维基百科):
回调机制的优势
从上面的例子可以看出,回调机制提供了非常大的灵活性。请注意,从现在开始,我们把图中的库函数改称为中间函数了。
这是因为回调并不仅仅用在应用和库之间,任何时候,只要想获得类似于上面情况的灵活性,都可以利用回调。这种灵活性是怎么实现的呢?
乍看起来,回调似乎只是函数间的调用,但仔细一琢磨,可以发现两者之间的一个关键的不同:
在回调中,我们利用某种方式,把回调函数像参数一样传入中间函数。
可以这么理解,在传入一个回调函数之前,中间函数是不完整的。换句话说,程序可以在运行时,通过登记不同的回调函数,来决定、改变中间函数的行为。
这就比简单的函数调用,要灵活太多了。
2.键盘响应
1.api
waitKey(delay )
在一个给定的时间内(单位ms)等待用户按键触发;如果用户没有按下键,则继续等待(循环)。有按键按下,返回按键的ASCII值。无按键按下,返回-1。
延时delay = 0 函数则延时无限长,必须有键按下才继续执行。
延时delay > 0 函数返回值为按下的键的ASCII码值,超时则返回-1。
waitKey(0),表示程序会无限制的等待用户的按键事件;
waitKey(1),表示程序每1ms检测一次按键,检测到返回按键值,检测不到返回-1;
waitKey(100),表示程序每100ms检测一次按键,检测到返回按键值,检测不到返回-1;
由于返回ascill值,用此方法,音视频控制wait一般是1
key = waitKey(1);
if (key == 'q')
{
destroyAllWindows();
}
2.实例代码
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
//w.show();
namedWindow("windows", WINDOW_NORMAL);
resizeWindow("windows", 500, 500);
Mat srcImage = imread("C:\\Users\\29492\\Desktop\\Qt +opencv\\project\\light contrast regulate\\car7.png");
//默认BGR
if (srcImage.empty())
{
printf("could not load image……\n");
}
imshow("windows", srcImage);
std::cout <<srcImage << std::endl;
Mat dst = Mat::zeros(srcImage.size(), srcImage.type());
while(1)
{
key = waitKey(1);
if (key == 'q')
{
destroyAllWindows();
break;
}
if (key == 'w')
{
cvtColor(srcImage,dst,COLOR_BGR2GRAY);
std::cout << "1" << std::endl;
imshow("windows", dst);
}
if (key == 'e')
{
cvtColor(srcImage, dst, COLOR_BGR2HSV);
std::cout << "2" << std::endl;
imshow("windows", dst);
}
if (key == 'r')
{
dst = Scalar(50, 50, 50);
add(srcImage, dst, dst);
std::cout << "3" << std::endl;
imshow("windows", dst);
}
}
return a.exec();
}