动态数量的GUI滑块,用回调中的值更新std :: vector

时间:2017-05-04 14:36:23

标签: c++ user-interface c++11 callback libigl

我尝试将动态数量的滑块添加到GUI窗口,并根据每个滑块的更改方式使用值更新std::vector<float>。 GUI库使用回调,我可以成功地为一个滑块(或者复制和粘贴滑块代码20次,但这不是解决方案),但是我有问题将滑块创建分解为function:如何告诉每个滑块它应该更新的向量中的元素,存在变量生命周期的问题。

我使用nanogui(或者特别是libigl,使用nanogui),但我认为这个问题实际上非常通用,也应该适用于其他GUI框架或情况。

这是一个如何添加一个滑块的代码的简短版本,它会更新my_values[0](注意我必须放置&#34; 0&#34;手动):

int main(int argc, char *argv[])
{
  igl::viewer::Viewer viewer;
  std::vector<float> my_values(50);
  viewer.callback_init = [&](igl::viewer::Viewer& viewer)
    {
    nanogui::Slider* slider = new nanogui::Slider(viewer.ngui->window());

    slider->setCallback([&](float value) {
      my_values[0] = value; // this slider sets the value at element '0'
      });

    viewer.ngui->addWidget("0", slider);

    viewer.screen->performLayout();
    return false;
  };

  viewer.launch();
}

现在如前所述,在viewer.callback_init中,我现在想添加50个这样的滑块,但显然我不想复制和粘贴滑块及其回调代码50次。但不知怎的,我需要传递my_values[i],即每个滑块要更新的向量中的哪个元素。 我试过这样的东西,但是没有用,因为在实际调用函数/回调时,变量value_id没有定义:

int main(int argc, char *argv[])
{
  igl::viewer::Viewer viewer;
  std::vector<float> my_values(50);

  auto add_slider = [&](igl::viewer::Viewer& viewer, std::vector<float>& my_values, int value_id, std::string value_name)
    {   
    nanogui::Slider* slider = new nanogui::Slider(viewer.ngui->window());

    slider->setCallback([&](float value) {
      my_values[value_id] = value; // offending line, 'value_id' is not initialized
      // also I'm using 'value_name' to give the slider a name - code omitted
      });
    return slider;
  };

  viewer.callback_init = [&](igl::viewer::Viewer& viewer) {

    // Now add all 50 sliders (in a for-loop in real code obviously):
    viewer.ngui->addWidget("0", add_slider(viewer, 0, "0"));
    viewer.ngui->addWidget("1", add_slider(viewer, 1, "1"));
    // etc.

    viewer.screen->performLayout();
    return false;
  };

  viewer.launch();
}

我尝试了各种各样的事情,使value_id成为一个(const)引用,甚至是std::shared_ptr<int>(我知道,可怕),但仍然value_id始终未在行my_values[value_id] = value;上初始化1}}。

我怎样才能做到这一点?我的猜测是它必须是GUI /回调编程中一个众所周知的模式/解决方案,我还没想到它。

1 个答案:

答案 0 :(得分:1)

不使用std::vector<float>存储滑块值,而是使用map<string, float>map<Slider*, float>。因此,无论何时调用回调,您都将知道要更新的变量(通过滑块的地址或名称)。

map<Slider*, float> my_values;
slider->setCallback([&](float value) {
      my_values[slider] = value; 
      });