1

我在试图绕过“推荐”的做事方式时遇到了烦人的事情。

所以,我有一堆卡片。我想让它在我发牌时成为整个场景中最后绘制的对象(典型bring_to_front功能)。

推荐的方法是添加到对象zValue直到它大于其他对象,但我希望通过明智地使用该stackBefore方法来消除相当“懒惰”的整数,该方法模拟重组对象添加到场景中的顺序。

当我在有限的集合中洗牌时,这非常有效(获取选定项目的列表,random.shuffle,对于 item do item.stackBefore(next item)),但在将卡片冒泡时它肯定不起作用整个场景的顶部。

我考虑将对象的副本添加到场景中,然后删除原始对象,但看起来我应该能够stackAfter像使用 Python 列表(insertAt或其他东西)时那样做。

示例代码:

  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)

这行得通。只是看起来有点……丑陋。

4

1 回答 1

1

self.scene.items返回堆叠顺序中的项目(链接)。所以如果你想要stackAfter一个项目,你可以只查询当前最顶层项目的z值,然后将新最顶层卡片的z值设置为一个更大的值。

item.setZValue(self.scene.items().first().zValue() + 1)

希望有帮助。

编辑为stackBeforesetZValue来自http://gitorious.org/qt/添加的 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();
}
于 2013-02-26T05:23:47.677 回答