Динамическое число ползунков GUI, которые обновляют std :: vector со значениями в обратных вызовах

Я пытаюсь добавить динамическое количество ползунков в окно графического интерфейса и обновить std::vector<float> со значениями в зависимости от того, как меняется каждый слайдер. Библиотека GUI использует обратные вызовы, и я могу успешно сделать это для одного слайдера (или при копировании&вставка кода ползунка 20 раз, но это не решение проблемы), однако у меня возникают проблемы, связанные с созданием ползунка в функцию: существуют проблемы с временем жизни переменной в том, как сообщить каждому ползунку, какой элемент в векторе он должен обновить.

Я использую nanogui (или, в частности, libigl, который использует nanogui), но я думаю, что проблема на самом деле довольно общая и должна применяться и к другим средам или ситуациям с графическим интерфейсом.

Вот краткая версия кода, как добавить один ползунок и его обновления my_values[0] (обратите внимание, я должен был поставить «0» вручную):

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 (постоянная) ссылка, даже std::shared_ptr<int> (Я знаю, ужасно), но все же value_id всегда не инициализируется в строке my_values[value_id] = value;,

Как я могу сделать это? Я предполагаю, что это должен быть известный шаблон / решение в программировании GUI / обратного вызова, я просто еще не понял это.

0

Решение

Вместо того, чтобы хранить значения ползунка в std::vector<float>использовать map<string, float> или же map<Slider*, float>, Следовательно, всякий раз, когда вызывается ваш обратный вызов, вы будете знать, какую переменную обновлять (по адресу или имени ползунка).

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]