C++ Nana 如何从全局列表框 * 指针访问列表框内索引 0 上的按钮?
C++ Nana How can I access a button on index 0 that is inside a listbox, from a global listbox* pointer?
我有一个 listbox
,它在第一列包含一个 text
字段和 button
。
我有一个指向 nana
listBox
:
的全局指针
listbox* listBox = nullptr;
我从 here:
中检索到了这个 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();
}
问题:
如何从全局 listbox*
指针访问 listbox
内索引 0
上的 button
?
我知道这不是最佳做法,但这里是:
创建了一个 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)
{
...
}
您正在尝试复杂地使用 nana::listbox
(or in the Wiki) 最复杂的功能,这是 Nana 中最复杂的小部件。
据我了解,您不会直接 "attach" 列表中每个项目的内联小部件。相反,列表本身会生成有限数量的小部件,并且在每个时刻 "inlines" 这些小部件中的一个只针对每个可见项目。为了做到这一点,列表需要知道如何创建小部件以及如何为每个项目 "update" 它,以及小部件如何响应不同的可能事件,以及如何更新相应的项目。
这是通过将实现虚拟接口 listbox::inline_notifier_interface
的对象 "factory" 附加到列表的其中一个类别的一列来实现的。这是您使用 the function of the listbox category:
的地方
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
return 一个 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))
.
我有一个 listbox
,它在第一列包含一个 text
字段和 button
。
我有一个指向 nana
listBox
:
listbox* listBox = nullptr;
我从 here:
中检索到了这个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();
}
问题:
如何从全局 listbox*
指针访问 listbox
内索引 0
上的 button
?
我知道这不是最佳做法,但这里是:
创建了一个 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)
{
...
}
您正在尝试复杂地使用 nana::listbox
(or in the Wiki) 最复杂的功能,这是 Nana 中最复杂的小部件。
据我了解,您不会直接 "attach" 列表中每个项目的内联小部件。相反,列表本身会生成有限数量的小部件,并且在每个时刻 "inlines" 这些小部件中的一个只针对每个可见项目。为了做到这一点,列表需要知道如何创建小部件以及如何为每个项目 "update" 它,以及小部件如何响应不同的可能事件,以及如何更新相应的项目。
这是通过将实现虚拟接口 listbox::inline_notifier_interface
的对象 "factory" 附加到列表的其中一个类别的一列来实现的。这是您使用 the function of the listbox category:
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
return 一个 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))
.