Qt无边框基类(支持拖拽、最大化动画、半屏动画、最大化拖拽还原)

提供FramelessWidget类,可以将任意QMainWindow或者QWidget作为主窗口的程序直接通过setCenterWidget函数设置为无边框窗口。

特点:
1.支持上、下、左、右及左上、左下、右上、右下四角总共八个方向的拖拽

2.支持窗口最大化时向下拖拽进行还原;

3.支持拖动窗口至窗口最上端的动画效果;

4.支持拖动窗口至左侧和右侧进行半屏显示的动画效果;

5.限制了不能将窗口拖出屏幕外面;

6.边框阴影的2种实现方式。

关键代码:

bool FramelessWidget::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::Resize)
    {
        int width = this->width();
        int height = this->height();

        //左侧描点区域
        rectLeft = QRect(0, padding, padding, height - padding * 2);
        //上侧描点区域
        rectTop = QRect(padding, 0, width - padding * 2, padding);
        //右侧描点区域
        rectRight = QRect(width - padding, padding, padding, height - padding * 2);
        //下侧描点区域
        rectBottom = QRect(padding, height - padding, width - padding * 2, padding);

        //左上角描点区域
        rectLeftTop = QRect(0, 0, padding, padding);
        //右上角描点区域
        rectRightTop = QRect(width - padding, 0, padding, padding);
        //左下角描点区域
        rectLeftBottom = QRect(0, height - padding, padding, padding);
        //右下角描点区域
        rectRightBottom = QRect(width - padding, height - padding, padding, padding);
    }
    else if (event->type() == QEvent::HoverMove)
    {
        QHoverEvent *hoverEvent = dynamic_cast(event);
        QPoint point = hoverEvent->pos();

        if (resizeEnable)
        {
            if (rectLeft.contains(point))
            {
                this->setCursor(Qt::SizeHorCursor);
            }
            else if (rectRight.contains(point))
            {
                this->setCursor(Qt::SizeHorCursor);
            }
            else if (rectTop.contains(point))
            {
                this->setCursor(Qt::SizeVerCursor);
            }
            else if (rectBottom.contains(point))
            {
                this->setCursor(Qt::SizeVerCursor);
            }
            else if (rectLeftTop.contains(point))
            {
                this->setCursor(Qt::SizeFDiagCursor);
            }
            else if (rectRightTop.contains(point))
            {
                this->setCursor(Qt::SizeBDiagCursor);
            }
            else if (rectLeftBottom.contains(point))
            {
                this->setCursor(Qt::SizeBDiagCursor);
            }
            else if (rectRightBottom.contains(point))
            {
                this->setCursor(Qt::SizeFDiagCursor);
            }
            else
            {
                this->setCursor(Qt::ArrowCursor);
            }
        }

        //根据当前鼠标位置,计算XY轴移动了多少
        int offsetX = point.x() - lastPos.x();
        int offsetY = point.y() - lastPos.y();

        //当前最大&拖动距离大于20
        if (pressed)
        {
            QPoint distance = point - lastPos;
            int length = distance.manhattanLength();
            if (length > 20)
            {
                if(this->isMaximized())
                {   //! 最大化-->恢复初始状态
                    QRect rect = this->normalGeometry();
                    int desX = lastPos.x() * rect.width() / this->geometry().width();
                    int desY = lastPos.y();
                    rect.moveTopLeft(point - QPoint(desX, desY));
//                    this->setGeometry(rect);
                    lastPos = QPoint(desX, desY);
                    setZeroMargin(false);
                    this->showNormal();

                    m_windowState = DefaultWindow;

                    moveEnable   = true;
                    resizeEnable = true;
                }
                else if(m_windowState == LeftHalfWindow || m_windowState == RightHalfWindow)
                {   //! 半屏-->恢复初始状态
                    int desX = lastPos.x() * m_lastRect.width() / this->geometry().width();
                    int desY = lastPos.y();
                    m_lastRect.moveTopLeft(point - QPoint(desX, desY));
                    this->setGeometry(m_lastRect);
                    m_windowState = DefaultWindow;

                    moveEnable   = true;
                    resizeEnable = true;
                }
            }
        }


        if (moveEnable)
        {
            if (pressed)
            {

                QRect _rect = QApplication::desktop()->availableGeometry();

                if (_rect.width() - mapToGlobal(point).x() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(_rect.width() / 2, 0, _rect.width() / 2, _rect.height()));
                        m_windowState = RightHalfWindow;
                        setZeroMargin(true);
                    }
                }
                else if (mapToGlobal(point).x() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(0, 0, _rect.width() / 2, _rect.height()));
                        m_windowState = LeftHalfWindow;
                        setZeroMargin(true);
                    }
                }
                else if (mapToGlobal(point).y() < 10)
                {
                    if (!m_baseWidget->m_bHelpWidhetShow)
                    {
                        m_bubbleWidget->setMagicPoint(point+pos());

                        m_baseWidget->startAnimation(this->geometry(), QRect(0, 0, _rect.width(), _rect.height()));
                        m_windowState = MaximumWindow;
                        setZeroMargin(true);
                    }
                }
                else
                {
                    m_baseWidget->hide();
                    setZeroMargin(false);
                }






                //! 限制不能拖到屏幕底部之外
                int height = QApplication::desktop()->availableGeometry().height();
                if(mapToGlobal(point).y() >= height)
                    offsetY = 0;
                this->move(this->x() + offsetX, this->y() + offsetY);
            }
        }

        if (resizeEnable)
        {
            if (pressedLeft)
            {
                int resizeW = this->width() - offsetX;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, rectY, resizeW, rectH);
                }
            }
            else if (pressedRight)
            {
                this->setGeometry(rectX, rectY, rectW + offsetX, rectH);
            }
            else if (pressedTop)
            {
                int resizeH = this->height() - offsetY;
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(rectX, this->y() + offsetY, rectW, resizeH);
                }
            }
            else if (pressedBottom)
            {
                this->setGeometry(rectX, rectY, rectW, rectH + offsetY);
            }
            else if (pressedLeftTop)
            {
                int resizeW = this->width() - offsetX;
                int resizeH = this->height() - offsetY;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
                }
            }
            else if (pressedRightTop)
            {
                int resizeW = rectW + offsetX;
                int resizeH = this->height() - offsetY;
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y() + offsetY, resizeW, resizeH);
                }
            }
            else if (pressedLeftBottom)
            {
                int resizeW = this->width() - offsetX;
                int resizeH = rectH + offsetY;
                if (this->minimumWidth() <= resizeW)
                {
                    this->setGeometry(this->x() + offsetX, this->y(), resizeW, resizeH);
                }
                if (this->minimumHeight() <= resizeH)
                {
                    this->setGeometry(this->x(), this->y(), resizeW, resizeH);
                }
            }
            else if (pressedRightBottom)
            {
                int resizeW = rectW + offsetX;
                int resizeH = rectH + offsetY;
                this->setGeometry(this->x(), this->y(), resizeW, resizeH);
            }
        }
    }
    else if (event->type() == QEvent::MouseButtonPress)
    {
        QMouseEvent *mouseEvent = dynamic_cast(event);
        if(mouseEvent->button() != Qt::LeftButton)
            return QObject::eventFilter(watched, event);
        rectX = this->x();
        rectY = this->y();
        rectW = this->width();
        rectH = this->height();
        lastPos = mouseEvent->pos();

        //判断按下的区域位置
        if (rectLeft.contains(lastPos))
        {
            pressedLeft = true;
        }
        else if (rectRight.contains(lastPos))
        {
            pressedRight = true;
        }
        else if (rectTop.contains(lastPos))
        {
            pressedTop = true;
        }
        else if (rectBottom.contains(lastPos))
        {
            pressedBottom = true;
        }
        else if (rectLeftTop.contains(lastPos))
        {
            pressedLeftTop = true;
        }
        else if (rectRightTop.contains(lastPos))
        {
            pressedRightTop = true;
        }
        else if (rectLeftBottom.contains(lastPos))
        {
            pressedLeftBottom = true;
        }
        else if (rectRightBottom.contains(lastPos))
        {
            pressedRightBottom = true;
        }
        else
        {
            pressed = true;
        }
    }
    else if (event->type() == QEvent::MouseMove)
    {
        //已用HoverMove处理
    }
    else if (event->type() == QEvent::MouseButtonRelease)
    {
        pressed = false;
        pressedLeft = false;
        pressedRight = false;
        pressedTop = false;
        pressedBottom = false;
        pressedLeftTop = false;
        pressedRightTop = false;
        pressedLeftBottom = false;
        pressedRightBottom = false;
        this->setCursor(Qt::ArrowCursor);

        if (m_baseWidget->m_bHelpWidhetShow)
        {
            switch (m_windowState) {
            case DefaultWindow:
                moveEnable   = true;
                resizeEnable = true;
                break;
            case LeftHalfWindow:
            case RightHalfWindow:
                m_lastRect = this->geometry();
                this->setGeometry(m_baseWidget->m_endRect);
                moveEnable   = false;
                resizeEnable = false;
                break;
            case MaximumWindow:
                this->showMaximized();
                moveEnable   = false;
                resizeEnable = false;
                setZeroMargin(true);
                break;
            }
        }

        m_baseWidget->stopAnimation();

    }
    else if(event->type() == QEvent::MouseButtonDblClick)
    {
        if(this->isMaximized())
        {
            setZeroMargin(false);
            this->showNormal();
            btn_max->setStyleSheet("QPushButton { border-image: url(:/pictures/max.png); background-color: transparent; }\
                                    QPushButton:hover { background-color: #5477a2; }\
                                    QPushButton:pressed { background-color: #5477a2; }");
            moveEnable = true;
            resizeEnable = true;
        }
        else
        {
            setZeroMargin(true);
            this->showMaximized();
            btn_max->setStyleSheet("QPushButton { border-image: url(:/pictures/restore.png); background-color: transparent }\
                                    QPushButton:hover { background-color: #5477a2; }\
                                    QPushButton:pressed { background-color: #5477a2; }");
            moveEnable = false;
            resizeEnable = false;
        }
    }

    return QObject::eventFilter(watched, event);
}

全套代码链接: 正在为您运送作品详情

你可能感兴趣的:(Qt,qt)