QObject儿童的顺序(战略问题)

时间:2010-01-02 14:09:50

标签: qt qt4 children qobject

对于我的一个项目,我有一个QObject派生对象树,它利用QObject的父/子功能来构建树。

这非常有用,因为我使用了信号和插槽,使用Qt的保护指针并期望父对象在删除子对象时删除它们。

到目前为止一切顺利。不幸的是,现在我的项目要求我管理/改变孩子的顺序。 QObject没有提供任何改变其子节点顺序的方法(例外:QWidget的raise()函数 - 但在这种情况下这没用)。 所以现在我正在寻找控制孩子秩序的策略。我有一些想法,但我不确定他们的优点和缺点:



选项A:自定义排序索引成员变量

使用int m_orderIndex成员变量作为排序键,并提供sortedChildren()方法,该方法返回按此键排序的QObject列表。

  • 易于实现现有的对象结构。
  • QObject::children()方法被覆盖时出现问题 - 当项目的订单发生变化时,在循环期间会导致问题,也比默认实施更昂贵。
  • 如果所有排序键相等或0 /默认值,则应回退到QObject对象顺序。

选项B:子级冗余列表

QList中维护一个冗余的子项列表,并在创建和销毁子项时为其添加子项。

  • 需要对添加/删除的对象进行昂贵的跟踪。这基本上导致第二个子/父跟踪和许多信号/时隙。 QObject已在内部完成所有这些工作,因此再次执行它可能不是一个好主意。也感觉像是为了改变孩子的顺序这样简单的事情而添加了很多膨胀。
  • 灵活性很好,因为可以根据需要修改儿童的QList。
  • 允许孩子多次进入QList,或者根本不进入(尽管它可能仍然是QObject的孩子)

选项C:......?

任何想法或反馈,特别是那些已经在自己的项目中解决过这个问题的人,都非常感谢。新年快乐!

5 个答案:

答案 0 :(得分:7)

过去几天我花了很多时间浏览所有这些选项,并与其他一些程序员仔细讨论过。我们决定选择选项A

我们管理的每个对象都是父对象的子对象。由于Qt没有提供任何重新排序这些对象的方法,我们决定为每个对象添加一个int m_orderIndex属性,默认为0。

每个对象都有一个访问函数sortedChildren(),它返回QObjectList个孩子。我们在该职能中所做的是:

  1. 使用普通QObject::chilren()函数获取所有可用子对象的列表。
  2. dynamic_cast我们的“基类”的所有对象,它提供m_orderIndex属性。
  3. 如果对象是可转换的,请将其添加到临时对象列表中。
  4. 使用qSort和自定义LessThan函数来确定qSort是否需要更改两个对象的顺序。
  5. 返回临时对象列表。
  6. 我们这样做是出于以下原因:

    • 现有代码(尤其是Qt自己的代码)可以继续使用children(),而不必担心副作用。
    • 我们可以在订单无关紧要的地方使用正常的children()功能,而不会造成任何性能损失。
    • 在我们需要有序儿童列表的地方,我们只需将children()替换为sortedChildren()并获得所需效果。

    这种方法的一个好处是,如果所有排序索引都设置为零,则子项的顺序不会改变。

    很抱歉回答我自己的问题,希望能够解决同样问题的人。 ;)

答案 1 :(得分:1)

怎么样......

  1. QList listChildren =(QList)children();
  2. sort listChildren
  3. foreach listChildren setParent(TempParent)
  4. foreach listChildren setParent(OriginalParent)

答案 2 :(得分:0)

令人讨厌的黑客:QObject::children()返回引用到const。你可以抛弃常量,从而直接操纵内部列表。

这是非常邪恶的,并且存在使QObject保持内部的迭代器无效的风险。

答案 3 :(得分:0)

我没有单独的选项C,但比较选项A和B,在任何一种情况下你都说~4个字节(32位指针,32位整数),所以我选择选项B,如你可以保持该列表的排序。

为了避免追踪儿童的额外复杂性,您可以作弊并保持列表整洁有序,但将其与过滤掉所有非儿童的sortedChildren方法结合起来。复杂性明智,这最终要围绕O(nlogm)(n =儿童,m =列表条目,假设m> = n,即总是添加儿童),除非您对儿童有大的转变。我们称之为C。

Quicksort,在您建议的选项A中,为您提供O(n2)(wc),但也要求您检索指针,跟踪它们,检索整数等。组合方法只需要一个指针列表(aught)是O(n))。

答案 4 :(得分:0)

我有同样的问题,我通过选项B解决了。跟踪并不困难,只需创建一个方法“void addChild(Type * ptr);”另一个删除子项目。

如果您将子项独家存储在每个项的私有/公共子列表(QList)中并删除QObject库,则不会遭受恶意冗余。它实际上很容易实现免费的自动子项(虽然这需要额外的父指针)。