QT图形视图框架:拖拽图形项改变尺寸

参考:QGraphicItem, 拖拽窗口大小例子

#include <QGraphicsObject>

class commonGraphicsPixmapItem : public QGraphicsObject
{
    Q_OBJECT
public:
    explicit commonGraphicsPixmapItem(QPixmap pixmap,QString title,QGraphicsItem *parent = nullptr);
    void setTitle(QString string);
    QString getTitle()const
    {
        return this->title;
    }
    void setTextColor(QColor color);
signals:
    void sendItemInfo(QVariant);

protected:
    QVariant itemChange(GraphicsItemChange change, const QVariant &value)override;
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)override;
    virtual QRectF boundingRect()const override;
    virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event)override;
    void mousePressEvent(QGraphicsSceneMouseEvent *event)override;
    void hoverMoveEvent(QGraphicsSceneHoverEvent* event)override;
    void mouseMoveEvent(QGraphicsSceneMouseEvent* event)override;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent* event)override;

private:
    void setNewPixmap();
    bool IsInResizeArea(const QPointF& pos);

    QPixmap pixmap;
    QString title;
    QColor textColor;
    QSizeF itemSize;
    bool isResizing;  //是否正在改变大小的过程中
};
const qreal g_cResizePos[] = {9, 6, 3};

commonGraphicsPixmapItem::commonGraphicsPixmapItem(QPixmap pixmap, QString title, QGraphicsItem *parent)
    :QGraphicsObject(parent)
{
    setAcceptHoverEvents(true);
    setFlag(QGraphicsItem::ItemIsMovable);
    setFlag(QGraphicsItem::ItemSendsScenePositionChanges);//图形项可发送位置变化信号
    setFlag(QGraphicsItem::ItemIsSelectable);
    setFlag(QGraphicsItem::ItemIsFocusable);
    this->pixmap = pixmap;
    this->title = title;
    this->textColor = QColor(Qt::red);
    this->itemSize = pixmap.size();
    isResizing = false;
}

QRectF commonGraphicsPixmapItem::boundingRect() const
{
//    QRectF rect = pixmap.rect();
//    rect.setHeight(rect.height() + 10);
//    return QRectF(rect);
    return  QRectF(0, 0, itemSize.width() + 10, itemSize.height() + 10);
}

void commonGraphicsPixmapItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
    QMenu menu;
    menu.setStyleSheet(QString("QMenu{background-color:#FFFFFF; border:1px solid #%1;}"
                               "QMenu::item{padding-right:15px;padding-top:5px;padding-bottom:5px;}"
                               "QMenu::item:checked{border: 1px solid #%2;background: #F2F2F2;}"
                               "QMenu::item:selected{color:#FFFFFF;background:#%1;}").arg(uiEditorColor::style_main_color).arg(uiEditorColor::style_hover_color));
    QAction * setPixmapAction = menu.addAction(tr("设置图片"));
    connect(setPixmapAction,&QAction::triggered,this,&commonGraphicsPixmapItem::setNewPixmap);
    menu.exec(event->screenPos());
}

void commonGraphicsPixmapItem::setNewPixmap()
{
    QString filepath = QFileDialog::getOpenFileName(nullptr, tr("设置图片"), QString(), "*.png *.jpg");
    if(filepath.isEmpty())
    {
        return;
    }
    QPixmap p;
    p.load(filepath);
    if(p.width() >= scene()->width() || p.height() >= scene()->height())
    {
        QMessageBox msg;
        msg.setAutoFillBackground(true);
        msg.setPalette(Qt::white);
        msg.setParent(nullptr, Qt::Dialog|Qt::WindowCloseButtonHint);
        msg.setText(tr("图片尺寸大于视图尺寸"));
        QPushButton * btn = (msg.addButton(tr("Yes"),QMessageBox::AcceptRole));
        btn->setCursor(Qt::PointingHandCursor);
        btn->setStyleSheet(QString("QPushButton{color: #FFFFFF;padding:6px 10px 6px 10px;border-radius:6px;font-weight:bold;background: #%1;}"
                                   "QPushButton:hover{background: #%2;}"
                                   "QPushButton:pressed{background: #%3;}"
                                   "QPushButton:disabled{background: #d8d8d8;}").arg(uiEditorColor::style_main_color)
                                                                                .arg(uiEditorColor::style_hover_color)
                                                                                .arg(uiEditorColor::style_press_color));
        msg.exec();
        return;
    }
    pixmap = p;
    update();
}

void commonGraphicsPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{   
    if(event->button() == Qt::LeftButton)
    {
        if(IsInResizeArea(event->pos()))
            isResizing = true;

        QGraphicsObject::mousePressEvent(event);
        emit sendItemInfo(this->title);
        emit sendItemInfo(this->textColor);
        return;
    }
    else if(event->button() == Qt::RightButton)
    {
        return;
    }
    return QGraphicsObject::mousePressEvent(event);
}

void commonGraphicsPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
    if (event->button() == Qt::LeftButton && isResizing)
        isResizing = false;
    else
        QGraphicsObject::mouseReleaseEvent(event);
}

void commonGraphicsPixmapItem::setTitle(QString string)
{
    this->title = string;
    update();
}

void commonGraphicsPixmapItem::setTextColor(QColor color)
{
    this->textColor = color;
    update();
}

QVariant commonGraphicsPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
    if ((change == ItemPositionChange || change == ItemPositionHasChanged) && scene()) // 控件发生移动
    {
        QPointF newPos = value.toPointF();
        QRectF rect(0, 0, scene()->width(), scene()->height());
        if (!rect.contains(newPos))//左上角
        {
            newPos.setX(qMin(rect.width(), qMax(newPos.x(), 0.0)));
            newPos.setY(qMin(rect.height(), qMax(newPos.y(), 0.0)));

//            newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left())));
//            newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top())));
            return newPos;
        }

        QRectF thisRectF = boundingRect();
        QPointF nowPos = QPointF(newPos.x() + thisRectF.width(),newPos.y());
        if(!rect.contains(nowPos))//右上角
        {
            newPos.setX(rect.width() - thisRectF.width());
            this->setPos(newPos);
            return newPos;
        }

        nowPos = QPointF(newPos.x(),newPos.y() + thisRectF.height());
        if(!rect.contains(nowPos))//左下角
        {
            newPos.setY(rect.height() - thisRectF.height());
            this->setPos(newPos);
            return newPos;
        }
    }
    return QGraphicsItem::itemChange(change, value);
}

void commonGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    Q_UNUSED(widget);
    painter->save();
    painter->setRenderHint(QPainter::Antialiasing);

    QRectF thisRectF = boundingRect();
    if(option->state & QStyle::State_Selected)
    {
        painter->setPen(QColor("#D8D8D8"));
        painter->drawRect(thisRectF);
        setZValue(2);
    }
    else
    {
        setZValue(1);
        painter->fillRect(thisRectF, QBrush(Qt::transparent));
    }

    if(!pixmap.isNull())
    {
        QRect rect = thisRectF.toRect();
        painter->drawPixmap(rect, pixmap);//绘制图片
    }

    if(!title.isEmpty())
    {
        QRectF textRect;
        textRect.setRect(0, 0, thisRectF.width(), 30);

        textRect.moveTo(QPoint(0,static_cast<int>((thisRectF.height() - 30)/2)));
        QPen p(Qt::SolidLine);
        p.setColor(textColor);
        p.setWidth(2);
        painter->setPen(p);
        QFont font = painter->font();
        font.setPixelSize(24);
        painter->setFont(font);
        painter->drawText(textRect, Qt::AlignCenter|Qt::AlignVCenter, title);//绘制文字
    }

    if(option->state & QStyle::State_Selected)
    {
        qreal w = thisRectF.width();
        qreal h = thisRectF.height();
        painter->setPen(Qt::red);
        for (int i = 0; i < 3; ++i)//三角形
            painter->drawLine(static_cast<int>(w - g_cResizePos[i]) , static_cast<int>(h), static_cast<int>(w), static_cast<int>(h - g_cResizePos[i]));
    }

    painter->restore();
}

void commonGraphicsPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
    if (isResizing || (IsInResizeArea(event->pos()) && isSelected()))
        setCursor(Qt::SizeFDiagCursor);
    else
        setCursor(Qt::ArrowCursor);

    QGraphicsObject::hoverMoveEvent(event);
}

void commonGraphicsPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    if (isResizing)
    {
        qreal w = event->pos().x();
        qreal h = event->pos().y();
        if (w > 0)
            itemSize.setWidth(w);
        if (h > 0)
            itemSize.setHeight(h);
        prepareGeometryChange();
    }
    else
    {
        QGraphicsObject::mouseMoveEvent(event);
    }
}

bool commonGraphicsPixmapItem::IsInResizeArea(const QPointF& pos)
{
    return (pos.x() - itemSize.width() + g_cResizePos[0]) > (itemSize.height() - pos.y());
}

效果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值