033-QtShadowDialog

48 阅读2分钟

QtShadowDialog

QWidget实现无边框带阴影窗体技术调研报告

一、实现原理

  1. 核心机制 无边框实现:通过
Qt::FramelessWindowHint

标志去除系统默认边框。

  • 阴影效果:

方案一:使用 QGraphicsDropShadowEffect 类实现快速阴影。

方案二:重写 paintEvent 使用 QPainter 绘制自定义阴影。

  1. 窗口状态管理 全屏/局部切换:通过 showFullScreen() 和 showNormal() 控制窗口状态,结合 windowState() 判断当前状态。 透明背景: setAttribute(Qt::WA_TranslucentBackground) 确保阴影可见。

二、实现流程图

graph TD 
    A[创建QWidget基类窗口] --> B{设置无边框}
    B -->|Qt::FramelessWindowHint| C[启用透明背景]
    C --> D{选择阴影方案}
    D -->|方案一| E[应用QGraphicsDropShadowEffect]
    D -->|方案二| F[重写paintEvent绘制阴影]
    E --> G[处理窗口拖动事件]
    F --> G 
    G --> H[状态切换优化]
    H --> I[输出最终窗体]

三、代码实现(方案二:QPainter绘制)

#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QPropertyAnimation>
 
class ShadowWindow : public QWidget {
    Q_OBJECT 
public:
    ShadowWindow(QWidget *parent = nullptr) : QWidget(parent) {
        // 无边框设置 
        setWindowFlags(Qt::FramelessWindowHint);
        setAttribute(Qt::WA_TranslucentBackground);
        
        // 阴影参数 
        m_radius = 10;          // 圆角半径
        m_offset = QPoint(0, 0); // 阴影偏移
        m_blurRadius = 20;      // 阴影模糊半径 
        m_color = QColor(0, 0, 0, 100); // 阴影颜色 
    }
 
protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); 
 
        // 绘制阴影 
        QLinearGradient gradient(rect().topLeft(), rect().bottomRight());
        gradient.setColorAt(0,  m_color);
        gradient.setColorAt(1,  Qt::transparent);
        painter.setBrush(gradient); 
        painter.setPen(Qt::NoPen); 
        painter.drawRect(rect().adjusted(-m_blurRadius,  -m_blurRadius, m_blurRadius, m_blurRadius));
 
        // 绘制圆角主体 
        QPainterPath path;
        path.addRoundedRect(rect().adjusted(m_blurRadius,  m_blurRadius, -m_blurRadius, -m_blurRadius), m_radius, m_radius);
        painter.fillPath(path,  Qt::white);
    }
 
    void mousePressEvent(QMouseEvent *event) {
        if (event->button() == Qt::LeftButton) {
            m_dragPos = event->globalPos() - frameGeometry().topLeft();
            event->accept();
        }
    }
 
    void mouseMoveEvent(QMouseEvent *event) {
        if (event->buttons() & Qt::LeftButton) {
            move(event->globalPos() - m_dragPos);
            event->accept();
        }
    }
 
private:
    int m_radius;
    QPoint m_offset;
    int m_blurRadius;
    QColor m_color;
    QPoint m_dragPos;
};

四、优化参数配置表

参数作用描述推荐取值范围示例代码片段
m_radius圆角半径5-20像素m_radius = 10;
m_blurRadius阴影模糊半径10-30像素m_blurRadius = 20;
m_color阴影颜色(带透明度)QColor(0,0,0,100)m_color = QColor(0,0,0,100);
AA_EnableHighDpi高DPI缩放适配true/falseQCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

五、技术调研对比

方案优点缺点适用场景
QGraphicsDropShadow代码简洁,跨平台兼容性好高DPI下可能出现错位1快速开发,简单阴影需求
QPainter自定义绘制完全控制阴影形状和动画需要手动处理性能优化高级视觉效果,动画需求
系统API调用原生系统阴影效果跨平台实现复杂9对系统一致性要求高的场景

六、结构图说明

classDiagram 
    QWidget <|-- ShadowWindow 
    ShadowWindow --> QGraphicsDropShadowEffect: 方案一 
    ShadowWindow --> QPainter: 方案二 
    ShadowWindow --> QMouseEvent: 拖动事件处理 
    ShadowWindow --> QPropertyAnimation: 动画效果 

七、全屏与局部状态处理

void ShadowWindow::toggleWindowState() {
    if (isFullScreen()) {
        showNormal();
        // 调整阴影参数 
        m_blurRadius = 20;
        update();
    } else {
        showFullScreen();
        // 优化全屏阴影 
        m_blurRadius = 10;
        update();
    }
}

八、注意事项

  1. 性能优化:复杂阴影建议使用QPainter.setRenderHint(QPainter::HighQualityAntialiasing)
  2. 跨平台测试:Windows/Linux/Mac的阴影渲染可能存在差异,需单独测试。
  3. 动画兼容性:结合QPropertyAnimation时需注意阴影效果的平滑过渡。

完整代码

Github

作者郑天佐
邮箱zhengtianzuo06@163.com
主页www.zhengtianzuo.com
githubgithub.com/zhengtianzu…







加QQ好友






加微信好友
关注微信公众号






支付宝赞助






微信赞助