欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Qt 可拖拽 大小可调 方框

程序员文章站 2022-06-17 09:38:56
...

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