Qt-jambi-interest Archive, November 2006
QGraphicsItem parent/child with clipping
Message 1 in thread
Hello,
I'm pretty new to Qt and Qt-Jambi and I'm currently playing around with
QGraphicsItem.
What I want to do is to add an item as the child of another item with the
parent item
defining the clipping bounds of the child item(s).
Right now my paint method looks like this:
public void paint(QPainter painter, QStyleOptionGraphicsItem
arg1, QWidget arg2) {
if (parentItem() != null) {
painter.setClipRect(parentItem().boundingRect());
painter.setClipping(true);
}
painter.setRenderHint(QPainter.RenderHint.Antialiasing);
painter.setPen(new QPen(QColor.black));
painter.setBrush(new QBrush(QColor.yellow));
painter.drawRect(rectangle);
}
Problem is: I can still move my child item outside the bounds of th parent
item and
it's not clipped at all.
I'm pretty sure I'm missing something really basic here - I'm just not sure
what ;)
Any pointers would really be appreciated.
Best regards,
Lennart Steinke
Message 2 in thread
Hi, Lennart.
Lennart Steinke wrote:
>What I want to do is to add an item as the child of another item with the
>parent item
>defining the clipping bounds of the child item(s).
>
>Right now my paint method looks like this:
>
> public void paint(QPainter painter, QStyleOptionGraphicsItem
>arg1, QWidget arg2) {
> if (parentItem() != null) {
>
>painter.setClipRect(parentItem().boundingRect());
>
>
The bounding rect of the parent is in the parent's coordinate system and
the painter is in the current item's coordinate system.
This should help:
QPainterPath path = new QPainterPath();
path.addPolygon(mapFromParent(parentItem().boundingRect());
painter.setClipPath(path);
Another way of achieving this for all your items is to override the
drawItems() method in QGraphicsScene. I've attached a quick example of
this, but please note that the we are currently working on fine tuning
the API where the class QNativePointer occurs (as this is an
inconvenient class to use.) Thus, this example will look different in
the next release of Qt Jambi, but it should illustrate the point, at least.
-- Eskil
import java.util.List;
import java.util.List;
import com.trolltech.qt.QNativePointer;
import com.trolltech.qt.core.QPointF;
import com.trolltech.qt.core.QRectF;
import com.trolltech.qt.core.QSizeF;
import com.trolltech.qt.core.Qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QBrush;
import com.trolltech.qt.gui.QColor;
import com.trolltech.qt.gui.QGradient;
import com.trolltech.qt.gui.QGraphicsItem;
import com.trolltech.qt.gui.QGraphicsItemInterface;
import com.trolltech.qt.gui.QGraphicsScene;
import com.trolltech.qt.gui.QGraphicsSceneMouseEvent;
import com.trolltech.qt.gui.QGraphicsView;
import com.trolltech.qt.gui.QLinearGradient;
import com.trolltech.qt.gui.QPainter;
import com.trolltech.qt.gui.QPainterPath;
import com.trolltech.qt.gui.QStyleOptionGraphicsItem;
import com.trolltech.qt.gui.QWidget;
public class GraphicsSceneClipping extends QGraphicsScene {
private static class Basket extends QGraphicsItem {
private QRectF boundingRect;
private QPainterPath shape;
private QGradient gradient;
public Basket(QSizeF size) {
boundingRect = new QRectF(-size.width() / 2, -size.height() / 2, size.width(), size.height());
shape = new QPainterPath();
shape.addEllipse(boundingRect);
gradient = new QLinearGradient(boundingRect.topLeft(), boundingRect.bottomLeft());
gradient.setColorAt(0.0, QColor.fromRgb(128, 128, 128, 200));
gradient.setColorAt(1.0, QColor.fromRgb(200, 200, 200, 200));
}
@Override
public QRectF boundingRect() {
return boundingRect;
}
@Override
public QPainterPath shape() {
return shape;
}
@Override
public void paint(QPainter painter, QStyleOptionGraphicsItem option, QWidget widget) {
painter.setBrush(new QBrush(gradient));
painter.drawPath(shape());
}
}
private static class Egg extends QGraphicsItem {
private QRectF boundingRect;
private QPainterPath shape;
private QGradient gradient;
public Egg(QSizeF size) {
boundingRect = new QRectF(0.0, 0.0, size.width(), size.height());
shape = new QPainterPath();
shape.addEllipse(boundingRect);
gradient = new QLinearGradient(boundingRect.topLeft(), boundingRect.bottomRight());
gradient.setColorAt(0.0, QColor.fromRgb(230, 230, 230, 200));
gradient.setColorAt(1.0, QColor.fromRgb(250, 250, 250, 200));
}
@Override
public QPainterPath shape() {
return shape;
}
@Override
public QRectF boundingRect() {
return boundingRect;
}
@Override
public void paint(QPainter painter, QStyleOptionGraphicsItem option, QWidget widget) {
painter.setBrush(new QBrush(gradient));
painter.drawPath(shape());
}
}
public static void main(String[] args) {
QApplication.initialize(args);
GraphicsSceneClipping scene = new GraphicsSceneClipping();
QGraphicsView view = new QGraphicsView();
view.setScene(scene);
view.setRenderHint(QPainter.RenderHint.Antialiasing);
view.show();
QApplication.exec();
}
private Basket baskets[] = new Basket[4];
private Egg eggs[] = new Egg[100];
public GraphicsSceneClipping() {
// Make baskets
for (int i=0; i<4; ++i) {
baskets[i] = new Basket(new QSizeF(200.0 - i * 30.0, 200.0 - i * 30.0));
addItem(baskets[i]);
baskets[i].setPos((i % 2) * 200.0, (i / 2) * 200.0);
baskets[i].setZValue(2.0);
}
// Make eggs
for (int i=0; i<100; ++i) {
eggs[i] = new Egg(new QSizeF(20.0, 50.0));
addItem(eggs[i]);
eggs[i].setPos(400.0 + Math.random() * 200.0, Math.random() * 400.0);
eggs[i].setZValue(5.0);
}
}
@Override
protected void drawItems(QPainter painter, int numItems, QNativePointer _items, QStyleOptionGraphicsItem options, QWidget widget) {
List<QGraphicsItemInterface> items = items(itemsBoundingRect());
for (int i = items.size()-1; i>=0; --i) {
QGraphicsItemInterface item = items.get(i);
painter.save();
painter.setMatrix(item.sceneMatrix(), true);
QPainterPath path = new QPainterPath();
if (item.parentItem() != null) {
path.addPath(item.mapFromParent(item.parentItem().shape()));
painter.setClipPath(path, Qt.ClipOperation.ReplaceClip);
}
painter.setClipRect(item.boundingRect().adjusted(-1.0, -1.0, 1.0, 1.0), Qt.ClipOperation.IntersectClip);
item.paint(painter, null, widget);
painter.restore();
}
}
private QGraphicsItemInterface draggedItem = null;
@Override
protected void mouseMoveEvent(QGraphicsSceneMouseEvent event) {
if (draggedItem != null) {
QPointF pos = event.scenePos();
if (draggedItem.parentItem() != null)
pos = draggedItem.parentItem().mapFromScene(pos);
draggedItem.setPos(pos);
}
}
@Override
protected void mousePressEvent(QGraphicsSceneMouseEvent event) {
draggedItem = itemAt(event.scenePos());
}
@Override
protected void mouseReleaseEvent(QGraphicsSceneMouseEvent event) {
if (draggedItem != null) {
List<QGraphicsItemInterface> items = items(event.scenePos());
if (draggedItem instanceof Egg) {
for (QGraphicsItemInterface basket : items) {
if (basket instanceof Basket) {
draggedItem.setParentItem(basket);
draggedItem.setPos(basket.mapFromScene(event.scenePos()));
break;
}
}
}
draggedItem = null;
}
}
}