0
votes

I am new at Qt and I want to write my custom QGraphicsItem which contains a rectangle and couple of buttons. I want to write a single custom component that could be easily added to QGraphicsScene and moved or resized with contents(buttons and rectangles) in it. In the end I want to add multiple customized QGraphicsItem to my QGraphicsScene. My question is how can I write this customized QGraphicsItem that contains buttons and rectangles which relative positions to each other are constant.

In this drawing green colored rectangles represent buttons and their relative position to each other always stays same (as if they are placed using qlayouts)

1
Check this example with anchors: doc.qt.io/qt-5/… for one approach. A different approach using child items is here: doc.qt.io/qt-5/…. Both of these examples should be available to you locally through the Creator. These should give you the general idea, then you can return if you have a more specific question.user9088793
@replete Drag and Drop Robot Example from doc.qt.io/qt-5/… helped me a lot. Thank you so muchBb Gg

1 Answers

0
votes

Thanks to @replete, from the example at http://doc.qt.io/qt-5/qtwidgets-graphicsview-dragdroprobot-example.html I was able to create a custom QGraphicsItem with clickable sub-parts in it. In code below BboxItem represents container QGraphicsItem and BboxItemContent represents childs of it. By emitting signals whith mause click events I was able to implement button like features. And I can move the BboxItem by setting its bounding rectangle.

BboxItem related source code:

BboxItemContent::BboxItemContent(QGraphicsItem *parent, int type, QColor color,QRectF *rect)
    : QGraphicsObject(parent)
{
    content_rectangle = rect;
    content_type = type;
    switch (type)
    {
    case 0:
        rectangle_color = color;
        icon = 0;
        break;
    case 1:
        icon = new  QImage(":/resource/assets/info_btn.png");
        break;
    case 2:
        icon = new  QImage(":/resource/assets/close_btn.png");
        break;
    }
}

BboxItemContent::~BboxItemContent()
{
    delete icon;
}

QRectF BboxItemContent::boundingRect() const
{
    return QRectF(content_rectangle->x(), content_rectangle->y(), content_rectangle->width(), content_rectangle->height());
}

void BboxItemContent::paint(QPainter *painter,
    const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if (icon == 0)
    {
        QPen pen(rectangle_color, 3);
        painter->setPen(pen);
        painter->drawRect(*content_rectangle);

    }
    else
    {
        painter->drawImage(*content_rectangle, *icon);
    }
}

void BboxItemContent::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
    emit bboxContentClickedSignal();
}

void BboxItemContent::setRect(QRectF *rect)
{
    content_rectangle = rect;
    update();
}

BboxItem::BboxItem(QGraphicsItem *parent,QRectF *itemRect) : BboxItemContent(parent,0,Qt::red, itemRect)
{
    setFlag(ItemHasNoContents);
    bbox_area = new BboxItemContent(this, 0, Qt::red, itemRect);
    info_btn = new BboxItemContent(this, 1, Qt::red, new QRectF(itemRect->x() - 30, itemRect->y(), 30, 30));
    connect(info_btn, &BboxItemContent::bboxContentClickedSignal, this, &BboxItem::onInfoClickedSlot);
    delete_btn= new BboxItemContent(this, 2, Qt::red, new QRectF((itemRect->x()+itemRect->width()), itemRect->y(), 30, 30));
    connect(delete_btn, &BboxItemContent::bboxContentClickedSignal, this, &BboxItem::onDeleteClickedSlot);
}

void BboxItem::onDeleteClickedSlot()
{
    //delete clicked actions
}
void BboxItem::onInfoClickedSlot()
{
    //info clicked actions
}

void BboxItem::setRect(QRectF *rect)
{
    bbox_area->setRect(rect);
    info_btn->setRect(new QRectF(rect->x() - 30, rect->y(), 30, 30));
    delete_btn->setRect(new QRectF((rect->x() + rect->width()), rect->y(), 30, 30));
}

Related Headers:

class BboxItemContent : public QGraphicsObject
{
    Q_OBJECT
public:
    BboxItemContent(QGraphicsItem *parent = 0, int type = 0, QColor color = Qt::red, QRectF *rect=nullptr);
    ~BboxItemContent();
    // Inherited from QGraphicsItem
    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0) override;
    void setRect(QRectF *rect);
signals:
    void bboxContentClickedSignal();
protected:
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
private:
    QImage *icon;
    QColor rectangle_color;
    QRectF *content_rectangle;
    int content_type;
};

class BboxItem : public BboxItemContent {
    Q_OBJECT
public:
    BboxItem(QGraphicsItem *parent = 0,QRectF *itemRect=nullptr);
    void setRect(QRectF *rect);
private slots:
    void onDeleteClickedSlot();
    void onInfoClickedSlot();
private:
    BboxItemContent *delete_btn;
    BboxItemContent *bbox_area;
    BboxItemContent *info_btn;
};