skytrails

QT 半透明遮罩(弹窗)

QT 透明遮罩(弹窗)

1.1 前言

​ 我们看Windows桌面应用,当你弹出一个提示弹窗,会发现弹窗有一个透明的遮罩,拖动遮罩应用界面跟随移动。这么设计一可以起到提示作用,二界面看起来很酷弦,三防止用户误操作。看下面的效果:

img

1.2 原理(技术点)

​ 今天我们用QT来实现这个功能,首先看下需要用到的技术点:

  • 无边框弹窗

    // 弹窗选择继承自QDialog
    class EShade : public QDialog{
      EShade(QWidget *parent){
        initStyle();
      }
      ~EShade();
    }
    
    // initStyle
    void initStyle() {
      setWindowFlags(Qt::FramelessWindowHint | windowFlags());// 去掉标题栏
      //TODO ADD CODE
      ...
    }
    
  • 半透明效果

    这个效果在网上查了有40%是用的paintEvent,还有59.99%用的是setWindowOpacity(0.2);我觉得这两种都不太好。前者太复杂,后者是对整个窗口实现半透明,包括了里面的子控件。这里介绍一种方便可控的方法:

    //不透明
    setStyleSheet("background: rgba(255, 255, 255, 1);");
    //半透明
    setStyleSheet("background: rgba(255, 255, 255, 0.5);");
    //全透明
    setStyleSheet("background: rgba(255, 255, 255, 0);");
    

全透明
不透明
半透明

PS:

​ 使用了setStyleSheet调成半透明后,子控件会继承父窗口的半透明效果,这时候只要在不需要半透明的位置放一个QFrame或者QLabel重新设置下背景色,并把子控件都放到QFrame/QLabel中。

  • 居中

    居中的实现方法很简单,计算好父窗口和需要居中的窗口大小,相减计算可得出位置,然后在构造函数中move到对应位置即可。

  • 同步主窗体

    这里要实现的是实现鼠标的拖动,并且弹窗移动了,父窗口也要跟随移动。

    这里用到QDialog的三个虛函数:

        // 鼠标按下事件
        virtual void mousePressEvent(QMouseEvent *event);
        // 鼠标移动事件
        virtual void mouseMoveEvent(QMouseEvent *event);
        // 鼠标释放事件
        virtual void mouseReleaseEvent(QMouseEvent *event);
    
    void EShade::mousePressEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton)
        {
            _bDrag = true;
            //获得鼠标的初始位置
            mouseStartPoint = event->globalPos();
            //获得窗口的初始位置
            windowTopLeftPoint = this->geometry().topLeft();
            parentTopLeftPoint = parentWidget()->frameGeometry().topLeft();
        }
    }
    
    void EShade::mouseMoveEvent(QMouseEvent *event)
    {
        if(_bDrag)
        {
            //获得鼠标移动的距离
            QPoint distance = event->globalPos() - mouseStartPoint;
            //改变窗口的位置
            this->move(windowTopLeftPoint + distance);
            parentWidget()->move(parentTopLeftPoint + distance);
        }
    }
    
    void EShade::mouseReleaseEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton)
        {
            _bDrag = false;
        }
    }
    
    

1.3 使用

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QPushButton *button = new QPushButton("弹出遮罩", this);
    button->show();
    QObject::connect(button, &QPushButton::clicked, [=]{
        EShade *shade = new EShade(this);
        shade->exec();
    });

    setStyleSheet("background: rgba(255, 255, 255, 1);");
}

源码

如需源码请在此下载
或联系我

skytrails@163.com

分类:

技术点:

QT

相关文章: