PDA

View Full Version : Container item implementation



onurozcelik
11th May 2010, 15:42
Hi, I am working in Train Traffic Controller software project. My responsibility in this project is to develop the visual railroad GUI.

We are implementing the project with Qt. By now I am using QGraphicsLinearLayout to hold my items. I am using the layout because I do not want to calculate coordinates of each item. So far I wrote item classes to add the layout. For instance SwitchItem class symbolizes railroad switch in real world. Each item class is responsible for its own painting and events. So far so good.
Now I need a composite item that can contain two or more item. This class is going to be responsible for painting the items contained in it. I need this class because I have to put two or more items inside same layout cell. If I don' t put them in same cell I can' t use layout. See the image below.

http://img169.imageshack.us/img169/9079/composite1.jpg BlockSegmentItem and SignalItem inside same cell.

Here is my compositeitem implementation.


#include "compositeitem.h"

CompositeItem::CompositeItem(QString id,QList<FieldItem *> _children)
{
children = _children;
}

CompositeItem::~CompositeItem()
{
}

QRectF CompositeItem::boundingRect() const
{
//Not carefully thinked about it
return QRectF(QPointF(-50,-150),QSizeF(250,250));
}

void CompositeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
FieldItem *child;
foreach(child,children)
{
child->paint(painter,option,widget);
}
}

QSizeF CompositeItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
QSizeF itsSize(0,0);
FieldItem *child;
foreach(child,children)
{
// if its size empty set first child size to itsSize
if(itsSize.isEmpty())
itsSize = child->sizeHint(Qt::PreferredSize);
else
{
QSizeF childSize = child->sizeHint(Qt::PreferredSize);
if(itsSize.width() < childSize.width())
itsSize.setWidth(childSize.width());
itsSize.setHeight(itsSize.height() + childSize.height());
}
}
return itsSize;
}

void CompositeItem::contextMenuEvent(QGraphicsSceneCont extMenuEvent *event)
{
qDebug()<<"Test";
}

This code works good with painting but when it comes to item events it is problematic. QGraphicsScene treats the composite item like a single item which is right for layout but not for events. Because each item has its own event implementation.(e.g. SignalItem has its special context menu event.)

I have to handle item events seperately. Also I need a composite item implementation for the layout. How can I overcome this dilemma?

tbscope
11th May 2010, 16:02
Check out this function:
http://doc.qt.nokia.com/4.6/qgraphicsitem.html#installSceneEventFilter

This way, you can handle the events of the children in your composite item and make a distinction between them

wysota
11th May 2010, 16:14
Instead of your class use QGraphicsWidget, place a layout inside it and place subitems into the layout. Then you can put the graphics widget into your main layout.

onurozcelik
12th May 2010, 10:13
Due to advice I changed boundingRect code.
I think this is a neat idea to unite child items boundingRects.


QRectF CompositeItem::boundingRect() const
{
FieldItem *child;
QRectF rect(0,0,0,0);
foreach(child,children)
{
rect = rect.united(child->boundingRect());
}
return rect;
}
But this time my composite item can' t catch events like contextmenuevent and mousepress event.
What may cause this?

onurozcelik
12th May 2010, 10:19
@wysota

If I've understood you corretly. You say "Change your code like this"


class CompositeItem : public QGraphicsLinearLayout
{
...
}


CompositeItem:CompositeItem(QString id, QList<FieldItem *> _children)
{
children = _children;
FieldItem *child;
foreach(child,children)
{
addItem(child);
}
}

Am I right?

wysota
12th May 2010, 10:23
The overall reason is that there are no child items in your item, you have a single item which is just drawing many items. You implemented boundingRect()... but did you also implement shape()? I don't really see the point of what you are doing as QGraphicsWidget and/or QGraphicsItemGroup already provide everything you want and need.

onurozcelik
12th May 2010, 13:00
I am using layouts and as far as I know QGraphicsItemGroup can not be added to a layout. That' s why I am using QGraphicsWidget.