C ++ Nana Как я могу получить доступ к кнопке в индексе 0, которая находится внутри списка, из глобального указателя списка *?

у меня есть listboxгде в первом столбце содержится text поле с button,

У меня есть этот глобальный указатель на nana listBox:

listbox*                listBox = nullptr;

у меня есть это class полученное из Вот:

#include <nana/gui.hpp>
#include <nana/gui/widgets/label.hpp>
#include <nana/gui/widgets/button.hpp>
#include <nana/gui/widgets/listbox.hpp>
#include <nana/gui/widgets/textbox.hpp>

#include <nana/gui/wvl.hpp>
#include <nana/system/platform.hpp>

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <thread>
#include <Windows.h>

using namespace nana;

//Creates a textbox and button
//textbox shows the value of the sub item
//button is used to delete the item.
class inline_widget : public listbox::inline_notifier_interface
{
private:
//Creates inline widget
//listbox calls this method to create the widget
//The position and size of widget can be ignored in this process
virtual void create(window wd) override
{
//Create listbox
txt_.create(wd);
txt_.events().click([this]
{
//Select the item when clicks the textbox
indicator_->selected(pos_);
});

txt_.events().mouse_move([this]
{
//Highlight the item when hovers the textbox
indicator_->hovered(pos_);
});

txt_.events().key_char([this](const arg_keyboard& arg)
{
if (arg.key == keyboard::enter)
{
//Modify the item when enter is pressed
arg.ignore = true;
indicator_->modify(pos_, txt_.caption());
}
});
//Or modify the item when typing
txt_.events().text_changed([this]()
{
indicator_->modify(pos_, txt_.caption());
});
//Create button
btn_.create(wd);
btn_.caption("Start");
btn_.enabled(false);
btn_.events().click([this]
{
//Delete the item when button is clicked
auto & lsbox = dynamic_cast<listbox&>(indicator_->host());
//buttonPressed(btn_, pos_.item);
});

btn_.events().mouse_move([this]
{
//Highlight the item when hovers the button
indicator_->hovered(pos_);
});
}

//Activates the inline widget, bound to a certain item of the listbox
//The inline_indicator is an object to operate the listbox item,
//pos is an index object refers to the item of listbox
virtual void activate(inline_indicator& ind, index_type pos)
{
indicator_ = &ind;
pos_ = pos;
}

void notify_status(status_type status, bool status_on) override
{
//Sets focus for the textbox when the item is selected
if ((status_type::selecting == status) && status_on)
txt_.focus();
}

//Sets the inline widget size
//dimension represents the max size can be set
//The coordinate of inline widget is a logical coordinate to the sub item of listbox
void resize(const size& dimension) override
{
auto sz = dimension;
sz.width -= 50;
txt_.size(sz);

rectangle r(sz.width + 5, 0, 45, sz.height);
btn_.move(r);
}

//Sets the value of inline widget with the value of the sub item
virtual void set(const value_type& value)
{
//Avoid emitting text_changed to set caption again, otherwise it
//causes infinite recursion.
if (txt_.caption() != value)
txt_.caption(value);
}

//Determines whether to draw the value of sub item
//e.g, when the inline widgets covers the whole background of the sub item,
//it should return false to avoid listbox useless drawing
bool whether_to_draw() const override
{
return false;
}

private:
inline_indicator * indicator_{ nullptr };
index_type pos_;
textbox txt_;
button btn_;
};

Это мое thread:

void theThread()
{
while (1)
{
//How can I access a button on index 0 from my listbox?
button* mybutton = listBox.at(0). ... ? -->HOW CAN I DO THIS?
mybutton->caption("I did it!!");
Sleep(1000);
}
}

И мой main() функция:

void main()
{
using namespace nana;
form fm(nana::API::make_center(750, 500), appear::decorate<appear::taskbar>());listbox lsbox(fm, rectangle{ 10, 50, 700, 200 });

listBox = &lsbox;

//Create columns
lsbox.append_header("Col1");
lsbox.append_header("Col2");
lsbox.append_header("Col3");
lsbox.append_header("Col4");
lsbox.append_header("Col5");

lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });
lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });
lsbox.at(0).append({ "text1", "text2", "text3", "text4", "text5" });

lsbox.column_at(0).width(200);

lsbox.at(0).inline_factory(0, pat::make_factory<inline_widget>());

fm.show();std::thread myThread(theThread);

exec();

myThread.join();

}

Вопрос:

Как я могу получить доступ к button по индексу 0 это внутри listboxиз моего глобального listbox* указатель?

1

Решение

Вы пытаетесь сделать сложное использование самой сложной функции nana::listbox (или в Wiki), самый сложный виджет в Нана.

Насколько я понимаю, вы напрямую не «прикрепляете» встроенный виджет к каждому элементу в списке. Вместо этого сам список генерирует ограниченное количество виджетов и в каждый момент «встраивает» один из этих виджетов в каждый и только в каждый видимый элемент. Для этого в списке необходимо знать, как создавать виджеты и как «обновлять» его для каждого элемента, а также как виджет реагирует на различные возможные события и как обновлять соответствующий элемент.

Это достигается путем прикрепления к одному столбцу одной из категорий списка «фабрики» объектов, реализующих виртуальный интерфейс listbox::inline_notifier_interface, Это где вы используете функция категории списка:

void nana::listbox::cat_proxy::inline_factory (size_type column,
pat::cloneable<pat::abstract_factory<inline_notifier_interface>> factory);

Это объясняет, почему нет прямого способа доступа к встроенным виджетам. Возможно, для этого можно будет реализовать новую функцию интерфейса в списке — мы попробуем. У меня вроде есть частная функция inline_pane * _m_get_inline_pane(const category_t& cat, std::size_t column_pos) const что вернуть inline_pane что в свою очередь содержит std::unique_ptr<inline_notifier_interface> inline_ptr; что можно проверить, если он пуст, и какой можно использовать для ссылки на вашу кнопку.
До сих пор ожидаемый способ повлиять на встроенный виджет — изменить содержание соответствующих элементов и использовать inline_notifier_interface чтобы отразить это изменение.

Что касается вашего обходного пути сохранения ссылки на кнопку в момент создания в глобальный вектор, вы можете предпочесть иметь глобальный вектор inline_widget потому что он включает в себя index_type pos_; что вы можете использовать для поиска этого вектора для элемента, который в настоящее время связан с объектом интереса. Конечно, вам будет трудно убедиться, что вектор указывает на живые объекты.

Возможно, вам придется отметить, что способ доступа к item_proxy с помощью lsbox.at(0).at(item_number), или же lsbox.at(index_pair(0,item_number)),

1

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

Я знаю, что это не лучшая практика, но здесь это идет:

Создано vector с pointers в buttons,

std::vector<button*>    mButtons;

На создание buttonЯ push_back() ссылка на vector:

    //Create button
btn_.create(wd);
btn_.caption("Start");
btn_.enabled(false);
btn_.events().click([this]
{
//Delete the item when button is clicked
auto & lsbox = dynamic_cast<listbox&>(indicator_->host());
//lsbox.erase(lsbox.at(pos_));
buttonPressed(btn_, pos_.item);
});

btn_.events().mouse_move([this]
{
//Highlight the item when hovers the button
indicator_->hovered(pos_);
});

mButtons.push_back(&btn_); // <--------- here

И теперь я могу контролировать buttons снаружи.

button* btn = mButtons[index];
if (nullptr != btn)
{
...
}
0

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