如何实现无边框带阴影的一个窗口呢,下面的代码可以参考下,适当的调整下自己的radiu来实现需要的效果,代码有注释
#ifndef CCSHADOWWIDGET_H
#define CCSHADOWWIDGET_H
#include <QWidget>
#include <QVector>
class CcShadowWidget : public QWidget
{
Q_OBJECT
public:
explicit CcShadowWidget(QWidget *parent = nullptr);
~CcShadowWidget();
protected:
virtual void paintEvent(QPaintEvent* event)override;
private:
void initWidget();
private:
int m_alphaValue = 30;//透明度
int m_radius = 6; //默认窗口的圆角半径
QVector<int> m_blurValue;//阴影渐变的颜色
QColor m_shadowColor = QColor("#65666e");//阴影的颜色
QColor m_backgroundColor = Qt::white;//窗口的背景颜色
};
#endif // CCSHADOWWIDGET_H
#include "CcShadowWidget.h"
#include <qmath.h>
#include <QPainter>
CcShadowWidget::CcShadowWidget(QWidget *parent)
:QWidget(parent)
{
initWidget();
}
CcShadowWidget::~CcShadowWidget()
{
}
void CcShadowWidget::initWidget()
{
//TODO: 设置默认窗口大小
resize(400,400);
//TODO: 设置窗口无边框/背景透明属性
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);//无边框的窗口
setAttribute(Qt::WA_TranslucentBackground,true);//实现圆角的无边框窗口必须设置的属性
//TODO: 初始化阴影的渐变值
qreal factor = m_alphaValue / m_radius;
for (int i = 0; i < m_radius; i++)
{
int level = (int)(m_alphaValue - qSqrt(i) * factor + 0.5);
m_blurValue.push_back(qMax<int>(0, level - 2));
}
}
void CcShadowWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
//TODO: 先填充背景,原来是透明的,用背景颜色进行填充
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRoundedRect(m_radius, m_radius, width() - m_radius * 2,
height() - m_radius * 2, m_radius, m_radius);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.fillPath(path, QBrush(m_backgroundColor));
//TODO: 再绘制圆角矩形path,利用渐变的颜色。
auto color = m_shadowColor;
for (int i = 0; i < m_radius; i++)
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRoundedRect(m_radius - i, m_radius - i, width() - (m_radius - i) * 2,
height() - (m_radius - i) * 2, m_radius, m_radius);
int alpha = 0;
if (i < m_blurValue.size())
{
alpha = m_blurValue[i];
}
color.setAlpha(alpha);
painter.setPen(color);
painter.drawPath(path);
}
}
- 结果
现在鼠标选中拖动是不能移动,其实挺简单的,只需要实现加上鼠标按下(QMousePressEvent)、鼠标移动(QMouseMoveEvent)、鼠标松开(QMouseReleaseEvent)这几个事件就可以
#ifndef CCSHADOWWIDGET_H
#define CCSHADOWWIDGET_H
#include <QWidget>
#include <QVector>
class CcShadowWidget : public QWidget
{
Q_OBJECT
public:
explicit CcShadowWidget(QWidget *parent = nullptr);
~CcShadowWidget();
protected:
virtual void paintEvent(QPaintEvent* event)override;
//为了能够让窗口移动,加上鼠标按下,松开,移动的事件处理
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void mousePressEvent(QMouseEvent *event) override;
virtual void mouseReleaseEvent(QMouseEvent *event) override;
private:
void initWidget();
private:
int m_alphaValue = 30;//透明度
int m_radius = 6; //默认窗口的圆角半径
QVector<int> m_blurValue;//阴影渐变的颜色
QColor m_shadowColor = QColor("#65666e");//阴影的颜色
QColor m_backgroundColor = Qt::white;//窗口的背景颜色
//能够移动窗口的属性
bool m_lefted = false;
QPoint m_leftPoint;
};
#endif // CCSHADOWWIDGET_H
#include "CcShadowWidget.h"
#include <qmath.h>
#include <QPainter>
#include <QMouseEvent>
CcShadowWidget::CcShadowWidget(QWidget *parent)
:QWidget(parent)
{
initWidget();
}
CcShadowWidget::~CcShadowWidget()
{
}
void CcShadowWidget::initWidget()
{
//TODO: 设置默认窗口大小
resize(400,400);
//TODO: 设置窗口无边框/背景透明属性
setWindowFlags(windowFlags() | Qt::FramelessWindowHint);//无边框的窗口
setAttribute(Qt::WA_TranslucentBackground,true);//实现圆角的无边框窗口必须设置的属性
//TODO: 初始化阴影的渐变值
qreal factor = m_alphaValue / m_radius;
for (int i = 0; i < m_radius; i++)
{
int level = (int)(m_alphaValue - qSqrt(i) * factor + 0.5);
m_blurValue.push_back(qMax<int>(0, level - 2));
}
}
void CcShadowWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPainter painter(this);
//TODO: 先填充背景,原来是透明的,用背景颜色进行填充
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRoundedRect(m_radius, m_radius, width() - m_radius * 2,
height() - m_radius * 2, m_radius, m_radius);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.fillPath(path, QBrush(m_backgroundColor));
//TODO: 再绘制圆角矩形path,利用渐变的颜色。
auto color = m_shadowColor;
for (int i = 0; i < m_radius; i++)
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRoundedRect(m_radius - i, m_radius - i, width() - (m_radius - i) * 2,
height() - (m_radius - i) * 2, m_radius, m_radius);
int alpha = 0;
if (i < m_blurValue.size())
{
alpha = m_blurValue[i];
}
color.setAlpha(alpha);
painter.setPen(color);
painter.drawPath(path);
}
}
void CcShadowWidget::mouseMoveEvent(QMouseEvent *event)
{
if (m_lefted)
{
//TODO: 鼠标移动时计算 (当前鼠标的位置- 按下鼠标位置的差= 窗口移动的距离)
QPoint offset = event->pos() - m_leftPoint;
move(offset + pos());
}
}
void CcShadowWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
//TODO: 记录鼠标按下时的位置(QPoint)
m_lefted = true;
m_leftPoint = event->pos();
}
}
void CcShadowWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
{
//TODO: 鼠标释放时重置下记录的数据
m_lefted = false;
m_leftPoint.setX(0);
m_leftPoint.setY(0);
}
}