实现功能
有时候我们的程序可能会需要弹出一个对话框,为了美观这个对话框后面需要半透明的遮罩。本文使用QWidget实现了一个半透明的遮罩,可以设置遮罩的大小,颜色,透明度以及遮罩内要显示的对话框,遮罩能够随着中央对话框的显示而显示,对话框的隐藏而隐藏,效果如下:
遮罩MaskForm的实现
想法是将要显示的对话框安装事件过滤器MaskForm,MaskForm拦截对话框的QEvent::Show和QEvent::Hide两个事件,与对话框进行同步显示隐藏,并在MaskForm的ShowEvent事件中确定显示的位置,代码如下
#ifndef MASKFORM_H
#define MASKFORM_H
#include <QWidget>
#include <QApplication>
class MaskForm : public QWidget
{
Q_OBJECT
public:
explicit MaskForm(QWidget *parent = 0);
~MaskForm();
/**
* @brief 注册要显示在遮罩中的窗口
* @param widget 要显示的窗口
*/
void installWidget(QWidget *widget);
/**
* @brief 设置遮罩的颜色,透明度
* @param color 遮罩颜色
* @param opacity 透明度
*/
void setMaskColor(const QColor &color, float opacity);
/**
* @brief 设置顶层窗口(覆盖窗口)
* @param widget 顶层窗口
*/
void setTopWidget(QWidget *widget);
private:
void init();
void showEvent(QShowEvent *event);
bool eventFilter(QObject *watched, QEvent *event);
private:
QWidget *m_topWidget; //顶层窗口,设置遮罩大小
QWidget *m_widget; //遮罩中显示的窗口
};
#endif // MASKFORM_H
#include "MaskForm.h"
#include <QDebug>
#include <QGridLayout>
MaskForm::MaskForm(QWidget *parent)
: m_widget(nullptr)
, m_topWidget(nullptr)
, QWidget(parent)
{
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()
{
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
setMaskColor(QColor(245, 125, 0), 0.6f);
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->show();
}
if (event->type() == QEvent::Hide) {
this->hide();
}
}
return QObject::eventFilter(watched, event);
}
MaskForm的使用
//使用遮罩
void DownLoadListForm::on_btnCreate_clicked()
{
MaskForm maskForm;
CreateDownloadDialog dlg(&maskForm);//将遮罩设置为中央窗口的父窗口
maskForm.installWidget(&dlg);//注册中央窗口,进行事件拦截
dlg.exec();
}