QGraphicsItem:为啥没有`stackAfter`方法?
Posted
技术标签:
【中文标题】QGraphicsItem:为啥没有`stackAfter`方法?【英文标题】:QGraphicsItem: Why no `stackAfter` method?QGraphicsItem:为什么没有`stackAfter`方法? 【发布时间】:2013-02-26 04:37:24 【问题描述】:我在尝试绕过“推荐”的做事方式时遇到了烦人的事情。
所以,我有一堆卡片。我想让它在我发牌时成为整个场景中最后绘制的对象(典型的bring_to_front
功能)。
推荐的方法是添加到对象的 zValue
直到它大于其他对象,但我希望通过明智地使用stackBefore
方法,它模拟重新组织对象添加到场景中的顺序。
当我在有限的集合中洗牌时,这非常有效(获取所选项目的列表,random.shuffle,对于 item do item.stackBefore(next item)),但在冒泡时它肯定不起作用卡到整个场景的顶部。
我考虑将对象的副本添加到场景中,然后删除原始对象,但似乎我应该能够像使用 Python 列表(或 insertAt
或其他东西)那样做 stackAfter
.
示例代码:
def deal_items(self):
if not self.selection_is_stack():
self.statusBar().showMessage("You must deal from a stack")
return
item_list = self.scene.sorted_selection()
for i,item in enumerate(item_list[::-1]):
width = item.boundingRect().width()
item.moveBy(width+i*width*0.6,0)
another_list = self.scene.items()[::-1]
idx = another_list.index(item)
for another_item in another_list[idx+1:]:
another_item.stackBefore(item)
这行得通。只是看起来有点……丑陋。
【问题讨论】:
也许有像setZValue=0
这样的技巧会自动将对象放在zValue==0 的所有对象的末尾?我不知道
【参考方案1】:
self.scene.items
按堆叠顺序返回项目 (link)。所以如果你想stackAfter
一个项目,你只需查询当前最顶层项目的z值,然后将新最顶层卡片的z值设置为大一即可。
item.setZValue(self.scene.items().first().zValue() + 1)
希望对您有所帮助。
编辑从http://gitorious.org/qt/ 为stackBefore
和setZValue
添加了src
src/gui/graphicsview/qgraphicsitem.cpp
void QGraphicsItem::stackBefore(const QGraphicsItem *sibling)
if (sibling == this)
return;
if (!sibling || d_ptr->parent != sibling->parentItem())
qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
return;
QList<QGraphicsItem *> *siblings = d_ptr->parent
? &d_ptr->parent->d_ptr->children
: (d_ptr->scene ? &d_ptr->scene->d_func()->topLevelItems : 0);
if (!siblings)
qWarning("QGraphicsItem::stackUnder: cannot stack under %p, which must be a sibling", sibling);
return;
// First, make sure that the sibling indexes have no holes. This also
// marks the children list for sorting.
if (d_ptr->parent)
d_ptr->parent->d_ptr->ensureSequentialSiblingIndex();
else
d_ptr->scene->d_func()->ensureSequentialTopLevelSiblingIndexes();
// Only move items with the same Z value, and that need moving.
int siblingIndex = sibling->d_ptr->siblingIndex;
int myIndex = d_ptr->siblingIndex;
if (myIndex >= siblingIndex)
siblings->move(myIndex, siblingIndex);
// Fixup the insertion ordering.
for (int i = 0; i < siblings->size(); ++i)
int &index = siblings->at(i)->d_ptr->siblingIndex;
if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
++index;
d_ptr->siblingIndex = siblingIndex;
for (int i = 0; i < siblings->size(); ++i)
int &index = siblings->at(i)->d_ptr->siblingIndex;
if (i != siblingIndex && index >= siblingIndex && index <= myIndex)
siblings->at(i)->d_ptr->siblingOrderChange();
d_ptr->siblingOrderChange();
void QGraphicsItem::setZValue(qreal z)
const QVariant newZVariant(itemChange(ItemZValueChange, z));
qreal newZ = newZVariant.toReal();
if (newZ == d_ptr->z)
return;
if (d_ptr->scene && d_ptr->scene->d_func()->indexMethod != QGraphicsScene::NoIndex)
// Z Value has changed, we have to notify the index.
d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, &newZ);
d_ptr->z = newZ;
if (d_ptr->parent)
d_ptr->parent->d_ptr->needSortChildren = 1;
else if (d_ptr->scene)
d_ptr->scene->d_func()->needSortTopLevelItems = 1;
if (d_ptr->scene)
d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
itemChange(ItemZValueHasChanged, newZVariant);
if (d_ptr->flags & ItemNegativeZStacksBehindParent)
setFlag(QGraphicsItem::ItemStacksBehindParent, z < qreal(0.0));
if (d_ptr->isObject)
emit static_cast<QGraphicsObject *>(this)->zChanged();
【讨论】:
确实如此(我喜欢first
电话,以前没见过),但我只想将zValues 用于完全不同的事情。我想过让 dz = 0.000001 这样我就不必担心突破障碍,但是我必须跟踪它并每隔一段时间不断重置值...... idk,我只是想从中挤出尽可能多的价值stackBefore 尽可能。
如果您需要另一个“z”变量,您可以子类化该项目并添加它。如果您之前阅读过堆栈文档,它所做的只是根据另一个对象的 z 值编辑 z 值。 qt-project.org/doc/qt-4.8/qgraphicsitem.html#stackBefore 祝你好运。
qt-project.org/doc/qt-4.8/qgraphicsitem.html#sorting 还谈到了使用育儿来对项目进行分组和排序 (ItemStacksBehindParent
)。
嘿@phyatt,在您的链接中它说“兄弟姐妹必须具有与此项目相同的 Z 值,否则调用此函数将无效。” “当Z值相同时,插入顺序将决定堆叠顺序。”这就是我要使用/修改的插入顺序。它似乎更健壮,非常适合我的目的。
我明白你的意思......但文档并没有指出任何简单的方法。你可以看看 stackBefore 是如何在源代码中实现的,并以这种方式创建一个类似的......以上是关于QGraphicsItem:为啥没有`stackAfter`方法?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 itemAt() 并不总能找到 QGraphicsItem
如果选择该项目,为啥 QGraphicsItem 子项不再单击鼠标?
为啥自定义 QGraphicsItem 会导致场景或视图移动,除非 boundingRect 为空?