这是我的问题:
在我正在开发的游戏 gui 中,“桌面”是一个我称为 WidgetManager 的类。为了让我在 gui 和小部件之间传达某些东西,比如焦点,每个小部件都必须有一个指向小部件管理器的指针。问题是,用户可以将 child 添加到还不是小部件管理器一部分的小部件。这就是我的 hacky 解决方案的用武之地:
AguiWidgetManager* AguiWidget::getWidgetManager() const
{
if(_container)
return _container;
if(getTopWidget())
{
if(getTopWidget()->getWidgetManager())
{
((AguiWidget*) this)->_container =
getTopWidget()->getWidgetManager();
return _container;
}
}
if(getParent())
{
if(getParent()->getWidgetManager())
{
((AguiWidget*) this)->_container =
getParent()->getWidgetManager();
return _container;
}
}
return (AguiWidgetManager*)NULL;
}
我知道这在多大程度上是一个糟糕的想法和糟糕的代码,并且打破了 consting 的要点,但我只是不确定如何确保小部件具有容器。
起初我想在添加时将小部件管理器指针设置为其父级的指针,但正如我所说,当时它的父级可能也没有。
谢谢
最佳答案
如果每个 Widget 都是由 WidgetManager 创建的,您可以在创建过程中将其传入。
不过,我认为您的问题来自于将 WidgetManager(最好称为 WidgetFactory)和顶级 Widget 的功能结合起来。我可以想到两种可能的解决方案,各有利弊。
1: 有一个 WidgetFactory 来生产 Widgets。在您的引擎中,保留指向根 Widget 的指针。这是您的桌面,所有要显示的小部件都必须是这个(树的基础)的子项。
渲染您的小部件时,您只需调用 RootWidget->Render()
,它就会递归地渲染它的子部件等等。
类似地,要从任何给定的 Widget 返回树,您调用 widget->GetParent()
并给出父级。进一步的调用将沿着树上升,直到到达根小部件,它没有父级(由引擎直接使用)。
那里的设置相对简单且易于使用,但您需要拆分小部件和创建小部件的东西。
2:如果您希望移动小部件工厂也充当小部件军队的操作基地,您可以为它提供一些与小部件相同的属性。最简洁的方法是让 WidgetManager 从 Widget 类派生,如下所示:
class Widget
{
virtual void Render() { for_each(mChildren, child->Render()); }
virtual Widget * GetParent(); // Returns pointer to parent
virtual WidgetType GetType() { return WT_Widget; }
private:
WidgetList mChildren;
Widget * mParent;
}
class WidgetManager
: public Widget
{
Widget * GetParent() { return NULL; }
WidgetType GetType() { return WT_Manager; }
}
这提供了一种处理两者的简单方法。 WidgetManager 有它的子项,并像每个 Widget 一样呈现它们,并且返回树的工作非常简单,因为您调用 widget->GetParent()
并且它适用于两者。
如果 GetParent() 返回 NULL,您可以通过调用 GetType 来验证您是否到达了 WidgetManager。如果返回 WT_Widget
,您可能遇到了问题。
编辑:您还可以让 WidgetManager 持有一个指向单个根小部件的指针,该小部件设置了一个标志以将其表示为顶部。然后使用方法 1 中的想法来处理小部件树的上下工作。
关于c++ - 确保一个小部件有一个容器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5508990/