FLTK:按下哪个按钮 - 将数字传递给按钮的回调(lambda)

Posted

技术标签:

【中文标题】FLTK:按下哪个按钮 - 将数字传递给按钮的回调(lambda)【英文标题】:FLTK: which button is pressed - passing a number to a button's callback (lambda) 【发布时间】:2020-02-19 22:00:15 【问题描述】:

我在 FLTK 窗口上有 N 按钮。我想知道用户按下了哪个按钮。如何将数字传递给每个按钮的 lambda 回调函数?到目前为止,我试过这个:

int main(int argc, char **argv) 
  Fl_Window *w_main = new Fl_Window(640, 480);

  std::vector<int> nums;
  for (int i = 0; i < 5; i++) 
    nums.push_back(i);

    Fl_Button *btn1 = new Fl_Button(50 * i, 0, 50, 50);
    char const *num = std::to_string(i).c_str();
    btn1->label(num);
    btn1->callback(
        [](Fl_Widget *w, void *data)  std::cout << "Clicked on: " << (int)data << std::endl; ,
        &nums[i]);
  
  w_main->show();
  return Fl::run();

不幸的是,我在输出中得到了类似随机的数字(我假设一些随机内存垃圾被解释为整数。)

你能帮我找到解决办法吗?谢谢!

【问题讨论】:

【参考方案1】:

当您注册回调时:

btn1->callback(
        ...,
        &nums[i]);

您将nums[i]地址 作为回调参数(而不是值本身)传递。因此,您需要将data 解释为所述地址,并取消引用它以访问底层号码。

这意味着:

btn1->callback(
        [](Fl_Widget *w, void *data)  std::cout << "Clicked on: " << *reinterpret_cast<int*>(data) << std::endl; ,
        &nums[i]);

您看到的“随机”数字绝不是随机的。它们代表您的号码所在的内存中的确切位置。将地址显式转换为数值是完全有效的代码,而这正是您所做的。

【讨论】:

【参考方案2】:

您也可以使用小部件的坐标来获取按钮的编号,因为您决定了按钮的位置。

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

#include <iostream>
#include <vector>

void show(Fl_Widget *w)
     std::cout << w->x()/50+1 << std::endl; 


int main(int argc, char **argv) 


  Fl_Window *w_main = new Fl_Window(640, 480);

  Fl_Button* bts[5];
  for (int i = 0; i < 5; i++) 
    char *num = new char;
    std::strcpy (num, std::to_string(i+1).c_str());

    bts[i] = new Fl_Button(50 * i, 0, 50, 50,num);
    
    bts[i]->callback(show);
  
  w_main->show();
  return Fl::run();

通过这种方式,您不必向回调传递任何内容。

【讨论】:

以上是关于FLTK:按下哪个按钮 - 将数字传递给按钮的回调(lambda)的主要内容,如果未能解决你的问题,请参考以下文章

FLTK 值更改和重绘等到回调之后:有啥办法吗?

带有按钮回调的新窗口未在 fltk 中打开

将键盘事件注入 FLTK 时遇到问题

存储来自回调 (FLTK) 的 Fl:Button 值

如何在自己的回调中访问 FLTK 按钮? [复制]

片段:按下返回按钮并自定义它时调用哪个回调