Qt实现阴影边框,可拖动,可缩放窗口(三)

阴影这部分,采用的是具有阴影的图片和九宫格的方式来实现的,之所以采用九宫格,就是为了让窗口缩放时不出现失真的问题。

#pragma once

#include <QWidget>
#include <QPaintEvent>
#include <QPixmap>

class CShadowWindow3 : public QWidget
{
    Q_OBJECT

public:
    explicit CShadowWindow3(QWidget* pShadowWidget,QWidget *parent = Q_NULLPTR);
    virtual ~CShadowWindow3();

protected:
    void paintEvent(QPaintEvent* pEvent) override;
    void resizeEvent(QResizeEvent* pEvent) override;
    void mousePressEvent(QMouseEvent* pEvent) override;
    void mouseReleaseEvent(QMouseEvent* pEvent) override;
    void mouseMoveEvent(QMouseEvent* pEvent) override;

    void InitConstruct();

    enum Direction
    {
        OUTER,
        LEFT_TOP,
        LEFT_BOTTOM,
        RIGHT_TOP,
        RIGHT_BOTTOM,
        CENTER,
        LEFT,
        RIGHT,
        TOP,
        BOTTOM
    };
    Direction CalcDirection(const QPoint& pt);
    void SetMouseCursorStyle(Direction direction);
    void DragAndResizeWidget(CShadowWindow3::Direction direction, const QPoint& ptOffset);

private:
    QWidget* m_pShadowWidget;
    QPixmap m_bmpBackground;

    int m_iShadowSize;

    QPoint m_ptPreGlobal;
    Direction m_Direction;
};

实现部分:

#include "CShadowWindow3.h"
#include <QPainter>
#include <QBrush>
#include <QtMath>
#include <QDebug>
#include <QApplication>
#include <QDir>

CShadowWindow3::CShadowWindow3(QWidget* pShadowWidget, QWidget *parent)
    : QWidget(parent),
    m_iShadowSize(12),
    m_pShadowWidget(pShadowWidget)
{
    //设置窗口无边框
    setWindowFlags(Qt::FramelessWindowHint);
    //设置窗口背景透明
    setAttribute(Qt::WA_TranslucentBackground, true);

    InitConstruct();
}

CShadowWindow3::~CShadowWindow3()
{
}

void CShadowWindow3::InitConstruct()
{
    QString strSkinFile = QString("%1%2skin%2Shadow.png").arg(qApp->applicationDirPath()).arg(QDir::separator());

    bool bFlag = m_bmpBackground.load(strSkinFile);

    //关联一个父窗口
    m_pShadowWidget->setParent(this);

    //设置阴影窗口大小
    const QSize sz = m_pShadowWidget->size();
    resize(m_iShadowSize + sz.width(), m_iShadowSize + sz.height());
    m_pShadowWidget->move(m_iShadowSize, m_iShadowSize);

    /*当鼠标不按下时,qt为了节省消耗,不会响应mousemove事件,所以需要设置true,这样即使不按下鼠标也会收到鼠标移动事件
    子窗口也要设置,是因为鼠标移动事件发生在了子窗口上,被拦截了
    */
    setMouseTracking(true);
    m_pShadowWidget->setMouseTracking(true);
}

void CShadowWindow3::resizeEvent(QResizeEvent*)
{
    QSize sz = size();
    m_pShadowWidget->setGeometry(m_iShadowSize, m_iShadowSize,
        qAbs(sz.width() - m_iShadowSize * 2), qAbs(sz.height() - m_iShadowSize * 2));
}

void CShadowWindow3::paintEvent(QPaintEvent*)
{
    //下列方式绘制的圆角阴影,边角有毛刺
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);

    const int iSize = m_iShadowSize*2;
    const QRect rcBmp = m_bmpBackground.rect();
    const QRect rcWnd = rect();
    //4个角落
    painter.drawPixmap(QRect(0, 0, iSize, iSize), m_bmpBackground, QRect(0, 0, iSize, iSize));
    painter.drawPixmap(QRect(rcWnd.width() - iSize, 0, iSize, iSize), m_bmpBackground,
        QRect(rcBmp.width() - iSize, 0, iSize, iSize));
    painter.drawPixmap(QRect(0, rcWnd.height()-iSize, iSize, iSize), m_bmpBackground, 
        QRect(0, rcBmp.height() - iSize, iSize, iSize));
    painter.drawPixmap(QRect(rcWnd.width() - iSize, rcWnd.height() - iSize, iSize, iSize), m_bmpBackground,
        QRect(rcBmp.width() - iSize, rcBmp.height() - iSize, iSize, iSize));

    //上下边
    painter.drawPixmap(QRect(iSize,0,rcWnd.width()-iSize*2,iSize), m_bmpBackground, 
        QRect(iSize, 0, rcBmp.width() - iSize * 2, iSize));
    painter.drawPixmap(QRect(iSize, rcWnd.height()-iSize, rcWnd.width() - iSize * 2, iSize), m_bmpBackground,
        QRect(iSize, rcBmp.height() - iSize, rcBmp.width() - iSize * 2, iSize));
    //左右边
    painter.drawPixmap(QRect(0, iSize, iSize, rcWnd.height() - iSize * 2), m_bmpBackground,
        QRect(0, iSize, iSize, rcBmp.height() - iSize * 2));
    painter.drawPixmap(QRect(rcWnd.width() - iSize, iSize, iSize, rcWnd.height() - iSize * 2), 
        m_bmpBackground,QRect(rcBmp.width() - iSize, iSize, iSize, rcBmp.height() - iSize * 2));
    return;
}

CShadowWindow3::Direction CShadowWindow3::CalcDirection(const QPoint& pt)
{
    if (pt.x() < m_iShadowSize && pt.y() < m_iShadowSize)
    {
        return LEFT_TOP;
    }
    else if (pt.x() < m_iShadowSize
        &&pt.y() > m_iShadowSize && pt.y() < rect().height() - m_iShadowSize)
    {
        return LEFT;
    }
    else if (pt.x() < m_iShadowSize &&pt.y() > rect().height() - m_iShadowSize)
    {
        return LEFT_BOTTOM;
    }
    else if (pt.x() > rect().width() - m_iShadowSize && pt.y() < m_iShadowSize)
    {
        return RIGHT_TOP;
    }
    else if (pt.x() > rect().width() - m_iShadowSize
        && pt.y() > m_iShadowSize && pt.y() < rect().height() - m_iShadowSize)
    {
        return RIGHT;
    }
    else if (pt.x() > rect().width() - m_iShadowSize
        && pt.y() > rect().height() - m_iShadowSize)
    {
        return RIGHT_BOTTOM;
    }
    else if (pt.x() > m_iShadowSize&&pt.x() < rect().width() - m_iShadowSize
        &&pt.y() < m_iShadowSize)
    {
        return TOP;
    }
    else if (pt.x() > m_iShadowSize&&pt.x() < rect().width() - m_iShadowSize
        &&pt.y() > rect().height() - m_iShadowSize)
    {
        return BOTTOM;
    }
    else if (pt.x() >= m_iShadowSize&&pt.y() >= m_iShadowSize
        &&pt.x() <= rect().width() - m_iShadowSize&&pt.y() <= rect().height() - m_iShadowSize)
    {
        return CENTER;
    }
    return OUTER;
}

void CShadowWindow3::SetMouseCursorStyle(Direction direction)
{
    switch (direction)
    {
    case TOP:
    case BOTTOM:
        setCursor(Qt::SizeVerCursor);
        break;
    case LEFT:
    case RIGHT:
        setCursor(Qt::SizeHorCursor);
        break;
    case LEFT_TOP:
    case RIGHT_BOTTOM:
        setCursor(Qt::SizeFDiagCursor);
        break;
    case RIGHT_TOP:
    case LEFT_BOTTOM:
        setCursor(Qt::SizeBDiagCursor);
        break;
    case CENTER:
        if (m_ptPreGlobal.isNull())
        {
            setCursor(Qt::ArrowCursor);
        }
        else
        {
            setCursor(Qt::SizeAllCursor);
        }
        break;
    default:
        setCursor(Qt::ArrowCursor);
    }
}

void CShadowWindow3::DragAndResizeWidget(CShadowWindow3::Direction direction, const QPoint& ptOffset)
{
    QRect rect = geometry();
    switch (direction)
    {
    case TOP:
        rect.setTop(rect.top() + ptOffset.y());
        break;
    case BOTTOM:
        rect.setBottom(rect.bottom() + ptOffset.y());
        break;
    case LEFT:
        rect.setLeft(rect.left() + ptOffset.x());
        break;
    case RIGHT:
        rect.setRight(rect.right() + ptOffset.x());
        break;
    case LEFT_TOP:
        rect.setTopLeft(rect.topLeft() + ptOffset);
        break;
    case RIGHT_BOTTOM:
        rect.setBottomRight(rect.bottomRight() + ptOffset);
        break;
    case RIGHT_TOP:
        rect.setTopRight(rect.topRight() + ptOffset);
        break;
    case LEFT_BOTTOM:
        rect.setBottomLeft(rect.bottomLeft() + ptOffset);
        break;
    case CENTER:
        break;
    default:;
    }
    if (rect.width() < m_iShadowSize * 3 || rect.height() < m_iShadowSize * 3)
    {
        return;
    }
    setGeometry(rect);
    return;
}

void CShadowWindow3::mousePressEvent(QMouseEvent* pEvent)
{
    if (Qt::LeftButton == pEvent->button())
    {
        m_ptPreGlobal = pEvent->globalPos();
        m_Direction = CalcDirection(pEvent->pos());
        SetMouseCursorStyle(m_Direction);
    }
}

void CShadowWindow3::mouseReleaseEvent(QMouseEvent* pEvent)
{
    m_ptPreGlobal = QPoint();
    setCursor(Qt::ArrowCursor);
}

void CShadowWindow3::mouseMoveEvent(QMouseEvent* pEvent)
{
    if (Qt::LeftButton&pEvent->buttons())
    {
        SetMouseCursorStyle(m_Direction);
        const QPoint ptNow = pEvent->globalPos();
        const QPoint ptOffset = ptNow - m_ptPreGlobal;
        m_ptPreGlobal = ptNow;
        if (Direction::CENTER == m_Direction)
        {
            move(pos() + ptOffset);
        }
        else
        {
            DragAndResizeWidget(m_Direction, ptOffset);
        }
    }
    else
    {
        SetMouseCursorStyle(CalcDirection(pEvent->pos()));
    }
}

例子:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    auto pWidget = new QWidget();
    pWidget->resize(200, 200);
    pWidget->setStyleSheet(QString("background-color: yellow"));
    auto pContainer = new CShadowWindow2(pWidget);
    pContainer->show();

    return a.exec();
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值