确保小部件有容器?

时间:2011-04-01 03:58:19

标签: c++ user-interface

这是我的问题:

在我正在开发的游戏中,“桌面”是我称之为WidgetManager的类。为了让我在gui和一个小部件之间传达某些事物,比如焦点,每个小部件都必须有一个指向小部件管理器的指针。问题是,用户可以将子项添加到小部件中,该小部件还不是小部件管理器的一部分。这是我的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;


}

我知道这在多大程度上是一个糟糕的想法和可怕的代码,并打破了常量,但我不确定如何确保小部件有一个容器。

首先我想到在添加它时将widget管理器指针设置为其父级的指针,但就像我说的那样,它的父级可能当时也没有。

由于

1 个答案:

答案 0 :(得分:1)

如果每个Widget都是由WidgetManager创建的,您可以在创建过程中传入它。

但是,我认为,你的问题来自于将WidgetManager(可能更好地称为WidgetFactory)和顶级Widget的功能结合起来。我可以想到两种可能的解决方案,包括利弊。

1:有一个生成小部件的WidgetFactory。在引擎中,保留指向根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中的想法来处理小部件树的工作。