一、背景
有时候我们需要实现下面的半透明遮罩效果,以便突出子窗口。
二、实现原理
1.总共分为三层:主窗口(Form)、遮罩、显示窗口。
2.主窗口的子窗口是遮罩,遮罩的子窗口是显示窗口。
3.遮罩设置为无边框,以及颜色和透明度等。
4.然后监控显示窗口事件,显示窗口显示,遮罩也跟着显示。关闭同理。
三、代码动态图下面
在这里插入图片描述

//遮罩头文件
class MaskForm : public QWidget
{
    Q_OBJECT

public:
    MaskForm(QWidget *parent = 0);
    ~MaskForm();

    //注册要显示在遮罩中的窗口
    void installWidget(QWidget *widget);

    //设置遮罩颜色、透明度
    void setMaskColor(const QColor &color,float opacity);

    //设置顶层窗口
    void setTopWidget(QWidget *widget);

private:
    void init();
    void showEvent(QShowEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);

private:
    QWidget *m_topWidget;    //顶层窗口,设置遮罩颜色、透明度
    QWidget *m_widget;       //遮罩中显示的窗口
};
//遮罩CPP文件
MaskForm::MaskForm(QWidget *parent)
    : QWidget(parent)
    ,m_topWidget(nullptr)
    ,m_widget(nullptr)
{
    init();
}

MaskForm::~MaskForm()
{

}

void MaskForm::installWidget(QWidget *widget)
{
    if(widget == nullptr)
    {
        return;
    }
	//监控显示窗口事件
    widget->installEventFilter(this);
    m_widget = widget;

    connect(m_widget, &QWidget::destroyed, this, [=](){
            m_widget = nullptr;});
}

void MaskForm::setMaskColor(const QColor &color, float opacity)
{
    if(!color.isValid())
    {
        return;
    }

    QPalette palette = this->palette();
    //通常指窗口部件的背景色
    palette.setColor(QPalette::Window,color);
    this->setPalette(palette);

    setWindowOpacity(opacity);
}

void MaskForm::setTopWidget(QWidget *widget)
{
	//设置遮罩父窗口
    if(widget == nullptr)
    {
        return;
    }
    m_topWidget = widget;
}

void MaskForm::init()
{
    /*
    Qt::FramelessWindowHint
    1.产生一个无边框的窗口,无法移动和改变大小。
    Qt::Tool
    1.工具窗口,如果有父窗口,则工具窗口将始终保留在它的顶部。
    2.默认情况下,当应用程序处于非活动状态时,工具窗口则消失。
    */
    setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
    setMaskColor(QColor(0,0,0),0.6f);

    //1.返回具有键盘输入焦点的顶级窗口,如果没有应用程序窗口具有焦点,则返回0.
    //2.但是即使没有焦点,也可能有一个活动窗口。例如一个窗口没有小部件接收关键事件。
    m_topWidget = QApplication::activeWindow();
}

void MaskForm::showEvent(QShowEvent *event)
{
    Q_UNUSED(event);
    //确定显示的位置
    this->setGeometry(m_topWidget->geometry());
}

bool MaskForm::eventFilter(QObject *watched, QEvent *event)
{
    if(watched == m_widget)
    {
        if(event->type() == QEvent::Show)
        {
        	//显示窗口显示,则遮罩显示,this就是遮罩本身
            this->show();
        }

        if(event->type() == QEvent::Hide)
        {
            this->hide();
        }
    }

    return QObject::eventFilter(watched, event);
}
//调用
void LoginDialog::on_pushButton_clicked()
{
    MaskForm *maskForm = new MaskForm(this);
    //设置遮罩的父窗口
    maskForm->setTopWidget(this);
	
	//构造显示窗口ToolTips
    ToolTips *toolTips = new ToolTips();
    //注册显示窗口,进行事件拦截(显示窗口开关,遮罩也跟着开关)。
    maskForm->installWidget(toolTips);
    toolTips->show();

}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐