天天看点

Qt 可拖拽 大小可调 方框

Abstract

参考QGraphicItem, 拖拽窗口大小例子基本思路,结合公司项目需要,写出可以拖拽及调整大小的边框,并且边框内可以划分2x2或3x3网格

效果图

Qt 可拖拽 大小可调 方框

演示视频

链接: https://pan.baidu.com/s/1HOsTZESZVSh933phqCc43Q 提取码: i9wc

需求总结

  1. 方框,可以划分网格
  2. 方框在指定范围内自由拖拽
  3. 可以拖拽方框四条边,改变方框大小
  4. 自适应缩放

分解+思路

可以参考Qt Window 大小调整,位置调整;

  • 位置移动/大小调整 = 鼠标响应 + rect size position调整 + boundary restriction;
  • 鼠标响应 = 鼠标press,move和hover event;
  • rect resize and position = mouse move + 原始size和position
  • boundary restriction = four vertex position check

部分代码

主要是event事件的里面处理方框移动,大小调整

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

判断方框移动是否出界

//方框移动和size变化
void SCGridReszableRectItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    if(m_resizing){
        qreal x = pos().x();
        qreal y = pos().y();
        qreal eventX = event->pos().x();
        qreal eventY = event->pos().y();
        qreal moveX = 0;
        qreal moveY = 0;
        qreal newW = m_size.width();
        qreal newH = m_size.height();
        QRectF rect = scene()->sceneRect();
        switch (m_curItemType) {
        case ITEM_TYPE::TOP:
            moveY = qMax(-y, eventY);
            newH = m_size.height() - moveY;
            break;
        case ITEM_TYPE::BOTTOM:
            newH = qMin(eventY, rect.height() - 2 - y);
            break;
        case ITEM_TYPE::LEFT:
            moveX = qMax(-x, eventX);
            newW = m_size.width() - moveX;
            break;
        case ITEM_TYPE::RIGHT:
            newW = qMin(eventX, rect.width() - 2 - x);
            break;
        case ITEM_TYPE::CENTER:
            break;
        }

        if(newH<minLength || newW<minLength) return;

        moveBy(moveX, moveY);
        m_size.setWidth(newW);
        m_size.setHeight(newH);

        prepareGeometryChange();
    }
    else{
        qreal moveX = 0;
        qreal moveY = 0;
        qreal eventX = event->pos().x();
        qreal eventY = event->pos().y();
        moveY = m_originPos.y() - eventY;
        moveX = m_originPos.x() - eventX;

        moveOutSide(-moveX, -moveY);
    }
}

//判断方框移动是否超出边界
void SCGridReszableRectItem::moveOutSide(qreal x, qreal y)
{
    QRectF rect = scene()->sceneRect();
    qreal itemX = pos().x();
    qreal itemY = pos().y();
    qreal limitW = rect.width() - m_size.width() - 2;
    qreal limitH = rect.height() - m_size.height() - 2;

    qreal newX = itemX + x;
    qreal newY = itemY + y;

    x = qMax(0.0, qMin(newX, limitW)) - itemX;
    y = qMax(0.0, qMin(newY, limitH)) - itemY;
    moveBy(x, y);
}
           

方框自适应scene size变化

//自适应大小
void SCGraphicsView::resizeEvent(QResizeEvent *event)
{
    QSize newSize = event->size();
    QSize oldSize =event->oldSize();
    qreal scaleX = 1.0;
    qreal scaleY = 1.0;

    this->scene()->setSceneRect(0, 0, newSize.width(), newSize.height());
    if(oldSize.width() <= 0)
        return;
    else{
        scaleX = static_cast<qreal>(newSize.width())/oldSize.width();
        scaleY = static_cast<qreal>(newSize.height())/oldSize.height();
    }

    QList<QGraphicsItem *>items = scene()->items();
    foreach(QGraphicsItem *item, items){
        if(item->type() == SCGridReszableRectItem::Type){
            SCGridReszableRectItem *t = static_cast<SCGridReszableRectItem *>(item);
            t->setScale(scaleX, scaleY);
            QPointF pos = t->pos();
            QPointF newPos = QPointF(pos.x() * scaleX, pos.y() * scaleY);
            t->setPos(newPos);
        }
    }
}
           

代码运行环境

Mac OS + Qt Creator 4.11.0 + Qt 5.14.1

下载链接:https://download.csdn.net/download/u013883974/12741834

继续阅读