QT QRect内含contains存在的问题及解决方法

452 阅读1分钟

背景

项目中应用到图片裁剪,裁剪框可以实时拖动,但是不可以超出图片所在的矩形。

分析

分析需求可知:存在两个矩形框,图片所在的矩形和裁剪框矩形。 针对于需求:裁剪框(矩形)不可以超出图片边界(矩形),即判断一个矩形必须在另一个矩形当中。

方法

QT QRect contains函数提供了内涵的计算方法

[]()bool QRect::contains(const [QRect](qrect.html#QRect) &rectangle, bool proper = false) const

Returns true if the given rectangle is inside this rectangle. otherwise returns false. If proper is true, this function only returns true if the rectangle is entirely inside this rectangle (not on the edge).
释义:

如果给定的矩形位于此矩形内,则返回 true。否则返回false。如果参数proper 为 true,则仅当矩形完全位于此矩形内(不在边缘上)时,此函数才返回 true。

原始代码

为实现功能(即满足需求)书写的原始代码如下

        //offset拖动的位移
        auto willGeometry = QRect(m_current_rect.topLeft()+offset,this->size());
        //m_original_rect 图片的矩形
        //willGeometry 拖动后的矩形
        if(m_original_rect.contains(willGeometry))
        {
            qDebug()<<"entirely contains ";
            this->setGeometry(willGeometry);
            this->move(willGeometry.topLeft());
        }

存在问题

但是该函数实现的具体效果差强人意,尤其是在图片的边缘(edge)部分时,裁剪框不可拖动了。比如:在顶(或底)部时,应该支持左右移动,但是移动失败;同理,在左(或右)端时,应该支持上下移动,但未支持。

解决方法

直接上代码

        if(m_original_rect.contains(willGeometry,true))//完全在里边
        {
             qDebug()<<"entirely contains ";
            this->setGeometry(willGeometry);
            this->move(willGeometry.topLeft());
        }
        else if(m_original_rect.contains(willGeometry,false)&&!m_original_rect.contains(willGeometry,true))//在边沿上
        {
            if(m_original_rect.top() == willGeometry.top()||m_original_rect.bottom() == willGeometry.bottom())
            {
                willGeometry = QRect(m_current_rect.topLeft()+QPoint(offset.x(),0),this->size());
                this->setGeometry(willGeometry);
                this->move(willGeometry.topLeft());
            }
            else if(m_original_rect.left() == willGeometry.left()||m_original_rect.right() == willGeometry.right())
            {
                willGeometry = QRect(m_current_rect.topLeft()+QPoint(0,offset.y()),this->size());
                this->setGeometry(willGeometry);
                this->move(willGeometry.topLeft());
            }
        }

通过两种方式的组合,就可以实现完全内含和在边沿的所有拖动