PDA

View Full Version : Can QGraphicsItems be layered between children of other QGraphicsItems?



philw
8th December 2010, 11:19
As default behavior of the QGraphicsItems "Z Values", independent Top-Level QGraphicsItems apparently can't be drawn between distinct "Z" layers of the nested QGrahpicsItem children of other Top-Level QGraphicsItems.

The Qt 4.6.3 example below shows these QGraphicsItems:

1. Top-Level QGraphicsRectItem .. Z = 1.0
2. ... Child QGraphicsTextItem .. Z = 3.0
3. Top-Level QGraphicsLineItem .. Z = 2.0

Notice that the Line Item obscures the Text Item, even though the Text Item has a higher Z-Value (but does not have the same parent QGraphicsItem). [Qt 4.6.3, 12-2010].

QUESTION: Are there any QGraphicsScene or QGraphicsItem configuration properties which can modify this behavior?

55775578
Images are also available here (https://cadswes2.colorado.edu/~philw/2010/Qt4AcctView/ZProblem/). See also screenshot of problem in our application (RiverWare) (https://cadswes2.colorado.edu/~philw/2010/Qt4AcctView/2010dec06/new.html).


// File: ZProblem.cpp
//
// QGraphicsItems:
// (1) Top-Level QGraphicsRectItem .. Z = 1.0
// (2) ... Child QGraphicsTextItem .. Z = 3.0
// (3) Top-Level QGraphicsLineItem .. Z = 2.0
//
// Notice that the Line Item obscures the Text Item, even though the
// Text Item has a higher Z-Value (but does not have the same parent
// QGraphicsItem). [Qt 4.6.3, 12-2010].

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsLineItem>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <ostream>

int main(int argc, char** argv)
{
QApplication app (argc, argv);
QGraphicsScene myScene;

// **************************************************
// *** Create Top-Level Rectangle QGraphicsItem ***
// **************************************************

const int RectWidth (300.0);
const int RectHeight (220.0);

QGraphicsRectItem* rectItem = new QGraphicsRectItem (
-0.5 * RectWidth, -0.5 * RectHeight, RectWidth, RectHeight);

rectItem->setBrush (QColor (0x66, 0xCC, 0xCC)); // blue-green
rectItem->setPen (QColor (Qt::black));
rectItem->setFlags (QGraphicsItem::ItemIsMovable);

rectItem->setZValue (1.0); // *** Z VALUE 1.0, Top-Level Item ***
rectItem->setToolTip ("Rectangle: Z = 1.0");

myScene.addItem (rectItem);

// *****************************************
// *** Create Child Text QGraphicsItem ***
// *****************************************

QGraphicsTextItem* childTextItem =
new QGraphicsTextItem ("ENIGMA", rectItem);

QFont textFont; // application default
textFont.setPixelSize (75);
textFont.setWeight (QFont::Black);
childTextItem->setFont (textFont);

childTextItem->setZValue (3.0); // *** Z VALUE 3.0, Child Item ***
childTextItem->setToolTip ("Child Text: Z = 3.0");

const QRectF childRect = childTextItem->boundingRect();
childTextItem->setPos (-0.5 * childRect.width(),
-0.5 * childRect.height());

// *********************************************
// *** Create Top-Level Line QGraphicsItem ***
// *********************************************

QGraphicsLineItem* lineItem = new QGraphicsLineItem (
-0.6 * RectWidth, 0.0, 0.6 * RectWidth, 0.0);

QPen linePen = QPen (QColor (0xFF, 0x66, 0x66)); // red
linePen.setCapStyle (Qt::RoundCap);
linePen.setWidth (20);
lineItem->setPen (linePen);
lineItem->setFlags (QGraphicsItem::ItemIsMovable);

lineItem->setZValue (2.0); // *** Z VALUE 2.0, Top-Level Item ***
lineItem->setToolTip ("Line: Z = 2.0");

myScene.addItem (lineItem);

// ******************************
// *** Create QGraphicsView ***
// ******************************

QGraphicsView myView (&myScene);
myView.setCaption ("Test QGraphicsItems Z-Values");
myView.resize (3.0 * RectWidth, 3.0 * RectHeight);
myView.show();

return app.exec();
}

Thank you in advance,
Phil Weinstein, CADSWES
University of Colorado at Boulder, USA

tbscope
8th December 2010, 11:39
As far as I understand the QGraphicsItem documentation, what you want is not possible "out of the box".

The Z value should be seen as a sorting value for the object tree.
The sorting is limited to children.

Example:

parent 1 Z = 0
child 1 Z = 1
child 2 Z = 2
child 2.1 Z = 3
parent 2 Z = 4

If you change the Z value of parent 2 to 2 for example, it will not affect the order since the only item that is considered is parent 1 which has a Z = 0
If you change child 1 to a Z value of 10, child 2 will be drawn before child 1, but parent 2 will still be drawn after the complete parent 1 is drawn.

You can change this behaviour though by implementing your own stacking.

There is a setting you can change though:
QGraphicsItem::ItemStacksBehindParent
But that doesn't do what you want either.

Disclaimer: I might have interpretted the documentation wrong though
http://doc.qt.nokia.com/4.7/qgraphicsitem.html#sorting

wysota
8th December 2010, 11:51
There is a simple rule - the Z-order applies to items within the same parent (siblings). Period. It's strictly an extension (or realization) of the "painter's algorithm". You cannot change this behaviour in any way other than breaking your parent-child hierarchy or doing the whole GV event processing on your own. It's also natural to the logic of the graphics view architecture - the item and all its children are seen by the environment (parent, cousins) of the item as a single item. Hence you cannot stick something "inbetween" such a hierarchy because from the point of view of the architecture there is no "inbetween".