2013-02-26 3 views
0

У меня время раздражает, пытаясь обойти «рекомендованный» способ сделать что-то.QGraphicsItem: Почему нет метода `stackAfter`?

Итак, у меня есть стопка карточек. Я хочу сделать так, чтобы при работе с картой он стал последним нарисованным объектом всей сцены (типичная функциональность bring_to_front).

Рекомендуемый способ сделать это - просто добавить к объекту zValue, пока он не станет больше, чем все остальные, но я надеялся покончить с довольно «ленивыми» целыми числами, работающими повсюду, с разумным использованием stackBefore, который имитирует реорганизацию порядка, в котором объекты были добавлены в сцену.

Это прекрасно работает, когда я перетасовываю свои карты в ограниченном наборе (получаю список выбранных предметов, random.shuffle, для элемента item.stackBefore (следующий элемент)), но он, безусловно, не работает, когда дело доходит до пузырящая карту до вершины всей сцены.

Я считал, добавив копию объекта на сцене, а затем удаляет оригинал, но это только кажется, что я должен быть в состоянии сделать 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) 

Это работает. Это просто кажется ... уродливым.

+0

может быть, есть трюк, как 'setZValue = 0' автоматически помещает объект в конце всех объектов с Zvalue == 0? я не знаю, – RodericDay

ответ

1

self.scene.items возвращает элементы в порядке укладки (link). Поэтому, если вы хотите указать stackAfter элемент, вы можете просто запросить значение z текущего верхнего элемента, а затем установить значение z новой верхней карты на значение больше.

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

Надежда, что помогает.

Редактировать добавил SRC для stackBefore и setZValue от http://gitorious.org/qt/ 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(); 
} 
+0

он делает (и мне нравится «первый» звонок, не видел его раньше), но я просто хочу использовать zValues ​​для другой вещи вообще. Я думал о создании dz = 0,000001, поэтому мне никогда не придется беспокоиться о нарушении барьеров, но потом я должен отслеживать его и постоянно переустанавливать значения каждый раз ... idk, мне просто кажется, что выжимаете столько же стоимости из stackBefore насколько возможно. – RodericDay

+0

Если вам нужна другая переменная «z», вы можете подклассифицировать элемент и добавить его. Если вы прочитали документ для стека раньше, все, что он делает, это редактирование значения z на основе значения z другого объекта. http://qt-project.org/doc/qt-4.8/qgraphicsitem.html#stackBefore Удачи. – phyatt

+0

http://qt-project.org/doc/qt-4.8/qgraphicsitem.html#sorting также рассказывает об использовании родительского контроля для группировки и сортировки элементов ('ItemStacksBehindParent'). – phyatt

Смежные вопросы