包含子 QGraphicsItems 的自定义 QGraphicsItem

Custom QGraphicsItem That Contains Child QGraphicsItems

我是 Qt 的新手,我想编写我的自定义 QGraphicsItem,它包含一个矩形和几个按钮。我想编写一个自定义组件,可以轻松地将其添加到 QGraphicsScene 并使用其中的内容(按钮和矩形)移动或调整大小。最后我想将多个自定义的 QGraphicsItem 添加到我的 QGraphicsScene 中。我的问题是如何编写这个自定义的 QGraphicsItem,它包含彼此相对位置不变的按钮和矩形。

在此图中,绿色矩形代表按钮,它们彼此的相对位置始终保持不变(就好像它们是使用 qlayouts 放置的一样)

感谢@replete,从 http://doc.qt.io/qt-5/qtwidgets-graphicsview-dragdroprobot-example.html 的示例中,我能够创建一个自定义 QGraphicsItem,其中包含可点击 sub-parts。在下面的代码中,BboxItem 代表容器 QGraphicsItem,而 BboxItemContent 代表它的孩子。通过发出带有误点击事件的信号,我能够实现类似按钮的功能。我可以通过设置边界矩形来移动 BboxItem。

BboxItem相关源码:

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));
}

相关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;
};