对于我的一个项目,我有一个QObject派生对象树,它利用QObject的父/子功能来构建树。
这非常有用,因为我使用了信号和插槽,使用Qt的保护指针并期望父对象在删除子对象时删除它们。
到目前为止一切顺利。不幸的是,现在我的项目要求我管理/改变孩子的顺序。 QObject没有提供任何改变其子节点顺序的方法(例外:QWidget的raise()函数 - 但在这种情况下这没用)。 所以现在我正在寻找控制孩子秩序的策略。我有一些想法,但我不确定他们的优点和缺点:
使用int m_orderIndex
成员变量作为排序键,并提供sortedChildren()
方法,该方法返回按此键排序的QObject列表。
QObject::children()
方法被覆盖时出现问题 - 当项目的订单发生变化时,在循环期间会导致问题,也比默认实施更昂贵。在QList
中维护一个冗余的子项列表,并在创建和销毁子项时为其添加子项。
任何想法或反馈,特别是那些已经在自己的项目中解决过这个问题的人,都非常感谢。新年快乐!
答案 0 :(得分:7)
过去几天我花了很多时间浏览所有这些选项,并与其他一些程序员仔细讨论过。我们决定选择选项A 。
我们管理的每个对象都是父对象的子对象。由于Qt没有提供任何重新排序这些对象的方法,我们决定为每个对象添加一个int m_orderIndex
属性,默认为0。
每个对象都有一个访问函数sortedChildren()
,它返回QObjectList
个孩子。我们在该职能中所做的是:
QObject::chilren()
函数获取所有可用子对象的列表。dynamic_cast
我们的“基类”的所有对象,它提供m_orderIndex
属性。qSort
和自定义LessThan
函数来确定qSort是否需要更改两个对象的顺序。我们这样做是出于以下原因:
children()
,而不必担心副作用。children()
功能,而不会造成任何性能损失。children()
替换为sortedChildren()
并获得所需效果。这种方法的一个好处是,如果所有排序索引都设置为零,则子项的顺序不会改变。
很抱歉回答我自己的问题,希望能够解决同样问题的人。 ;)
答案 1 :(得分:1)
怎么样......
答案 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库,则不会遭受恶意冗余。它实际上很容易实现免费的自动子项(虽然这需要额外的父指针)。