FLTK按钮回调能否传递多参数?报错问题求解
FLTK按钮回调传递多个参数的问题
错误信息
调用wK->callback(...)时触发以下两个错误:
- no instance of overloaded function "Fl_Button::callback" matches the argument list
- 'Fl_Widget::callback': no overloaded function takes 3 arguments
问题背景
用FLTK开发国际象棋程序,已实现传递单个数值参数的按钮回调,现在需要在回调中执行window->hide();,因此要向回调传递Fl_Window对象(回调中需转回原类型)。代码逻辑为循环调用setup函数直到一方获胜,通过关闭窗口实现界面刷新,所有函数已在头文件正确定义,这是当前唯一错误。
相关代码
int Board::setup(int argc, char** argv, std::vector<Piece*> wow, int turn) { Fl_Window* mainWindow = new Fl_Window(640, 640); // 创建窗口 // 绘制背景方格 for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { if ((x % 2 == 1 && y % 2 == 0) || (x % 2 == 0 && y % 2 == 1)) { Fl_Box* box = new Fl_Box(x * 80, y * 80, 80, 80); box->box(FL_FLAT_BOX); box->color(FL_BLACK); } } } // 绘制棋子 if (turn % 2 == 1) { whiteButtons(wow, argc, argv, mainWindow); } if (turn % 2 == 0) { blackButtons(wow, argc, argv, mainWindow); } mainWindow->show();// 启动主循环 return Fl::run(); } void Board::whiteButtons(std::vector<Piece*> wow, int argc, char** argv, Fl_Window* w){ Fl_Button* wK = new Fl_Button(wow[0]->yPos * 80, wow[0]->xPos * 80, 80, 80, u8"\u2654");// Unicode棋子符号 wK->box(FL_NO_BOX); wK->labelsize(48); wK->callback(firstPClicked, (void *)0, (void *)w);// 0为棋子在vector中的位置 // VS中callback被标红报错 } // blackButtons代码省略,逻辑与whiteButtons完全一致 void firstPClicked(Fl_Widget* f, void* d, void* w) {// 类型转换相关 if (((int*)d) == 0) { firstP = 0; ((Fl_Window*)w)->hide(); } }
FLTK常规回调语法示例
void balls(int* argc, char** argv){ Fl_Window *deez = new Fl_Window(300, 300); Fl_Button *nuts = new Fl_Button(100, 100, 100, 100, "Funny"); nuts->callback(imSoFunny, (void*)0); } void imSoFunny(Fl_Widget *w, void* d){ if (d == 0){ std::cout << "ahhh"; } }
解决方法
FLTK的Fl_Widget::callback仅支持最多两个参数:回调函数指针和一个void*类型的用户数据,无法直接传递多个参数。需将多个参数打包成结构体,再把结构体指针转为void*传递给回调,回调内再转回结构体类型使用。
- 定义封装参数的结构体
struct CallbackData { int pieceIndex; // 棋子在vector中的位置 Fl_Window* window; // 需要操作的窗口对象 };
- 修改按钮回调的参数传递逻辑
void Board::whiteButtons(std::vector<Piece*> wow, int argc, char** argv, Fl_Window* w){ Fl_Button* wK = new Fl_Button(wow[0]->yPos * 80, wow[0]->xPos * 80, 80, 80, u8"\u2654"); wK->box(FL_NO_BOX); wK->labelsize(48); // 创建并初始化回调数据结构体 CallbackData* data = new CallbackData(); data->pieceIndex = 0; data->window = w; // 传递结构体指针作为用户数据 wK->callback(firstPClicked, (void*)data); }
- 修改回调函数以解析结构体参数
void firstPClicked(Fl_Widget* f, void* d) { CallbackData* data = static_cast<CallbackData*>(d); if (data->pieceIndex == 0) { firstP = 0; data->window->hide(); } // 释放结构体内存,避免泄漏 delete data; }
若按钮与窗口生命周期完全一致,也可通过全局变量或类成员变量传递窗口指针,但结构体封装的方式耦合度更低、更规范。
内容的提问来源于stack exchange,提问作者esdv123
相关产品推荐
相关产品推荐

