包含子QGraphicsItems的自定义QGraphicsItem

时间:2018-12-13 12:35:53

标签: c++ qt qt5 qgraphicsscene qgraphicsitem

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

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

1 个答案:

答案 0 :(得分:0)

感谢@replete,根据http://doc.qt.io/qt-5/qtwidgets-graphicsview-dragdroprobot-example.html的示例,我能够创建一个自定义的QGraphicsItem,其中包含可单击的子部分。在下面的代码中,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));
}

相关标题:

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