实现对话框遮罩

  • 功能:1)遮罩自动触发; 2)遮罩颜色、透明度、尺寸人为设置; 3)通过单例模式,调用简单、安全。

  • 头文件maskwidget.h
#ifndef MASKWIDGET_H
#define MASKWIDGET_H
 
#include <QWidget>
 
class CMaskWidget : public QWidget
{
public:
	static CMaskWidget* GetInstance();
	static void UnInstance();
 
	//! 设置被遮盖的控件
	void SetMainWidget(QWidget *pWidgetMasked);
 
	/*
	 * \brief: 设置触发遮盖动作的控件名字
	 *
	 * \param[in]: lstWidgetNames 控件名字数组
	 */
	void SetDialogNames(const QStringList &lstWidgetNames);
 
	/*
	 * \brief: 设置透明度
	 *
	 * \param[in]: fOpacity 透明度 取值范围0-1 1: 完全透明; 0: 完全不透明
	 */
	void SetOpacity(float fOpacity);
 
protected:
	virtual void paintEvent(QPaintEvent *event) override;
	virtual void showEvent(QShowEvent* event) override;
	virtual bool eventFilter(QObject *obj, QEvent *event) override;
 
private:
	explicit CMaskWidget(QWidget* wgt = nullptr);
	~CMaskWidget();
 
private:
	static CMaskWidget* m_pMask;
	QWidget* m_pDlgToBeMasked = nullptr;
	QStringList m_lstNamesForDlgPrompt;
};
 
#endif // MASKWIDGET_H
  • 实现文件maskwidget.cpp
#include "maskwidget.h"
#include <QMutex>
#include <QEvent>
#include <QPainter>
#include <QApplication>
 
CMaskWidget* CMaskWidget::m_pMask = nullptr;
 
CMaskWidget* CMaskWidget::GetInstance()
{
	static QMutex s_Mutex;
	if (nullptr == m_pMask)
	{
		QMutexLocker locker(&s_Mutex);
		if (nullptr == m_pMask)
		{
			m_pMask = new CMaskWidget;
			m_pMask->setAttribute(Qt::WA_DeleteOnClose);
		}
	}
	return m_pMask;
}
 
void CMaskWidget::UnInstance()
{
	static QMutex s_Mutex;
	if (nullptr != m_pMask)
	{
		QMutexLocker locker(&s_Mutex);
		if (nullptr != m_pMask)
		{
			delete m_pMask;
			m_pMask = nullptr;
		}
	}
}
 
void CMaskWidget::SetMainWidget(QWidget *pWidgetMasked)
{
	if (m_pDlgToBeMasked != pWidgetMasked)
	{
		m_pDlgToBeMasked = pWidgetMasked;
		setGeometry(m_pDlgToBeMasked->geometry());
	}
}
 
void CMaskWidget::SetDialogNames(const QStringList &lstWidgetNames)
{
	if (m_lstNamesForDlgPrompt != lstWidgetNames)
	{
		m_lstNamesForDlgPrompt = lstWidgetNames;
	}
}
 
void CMaskWidget::SetOpacity(float fOpacity)
{
	setWindowOpacity(fOpacity);
}
 
void CMaskWidget::paintEvent(QPaintEvent *event)
{
	QPainter painter(this);
 
	painter.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
	painter.setBrush(QBrush(QColor(0, 0, 0, 125)));
	painter.setPen(Qt::transparent);
 
	QRect rect = this->rect();
	rect.setWidth(rect.width());
	rect.setHeight(rect.height());
 
	QPainterPath painterPath;
	painterPath.addRoundedRect(rect, 15, 15);
	painter.drawPath(painterPath);
 
	QWidget::paintEvent(event);
}
 
void CMaskWidget::showEvent(QShowEvent* event)
{
	if (nullptr != m_pDlgToBeMasked)
	{
		//! 获取被遮盖的窗口的宽高
		QRect rectDlgMasked = m_pDlgToBeMasked->geometry();
		int nWidth = rectDlgMasked.width();
		int nHeight = rectDlgMasked.height();
		setGeometry(0, 0, nWidth, nHeight);
	}
	QWidget::showEvent(event);
}
 
bool CMaskWidget::eventFilter(QObject *obj, QEvent *event)
{
	if (QEvent::Show == event->type()) 
	{
		if (m_lstNamesForDlgPrompt.contains(obj->objectName())) 
		{
			this->setVisible(true);
		}
	}
	else if (QEvent::Hide == event->type()) 
	{
		if (m_lstNamesForDlgPrompt.contains(obj->objectName())) 
		{
			this->setVisible(false);
		}
	}
	return QWidget::eventFilter(obj, event);
}
 
CMaskWidget::CMaskWidget(QWidget* wgt /* = nullptr */)
{
	setWindowFlags(windowFlags()
		| Qt::FramelessWindowHint);
	setAttribute(Qt::WA_TranslucentBackground);
}
 
CMaskWidget::~CMaskWidget()
{
	m_lstNamesForDlgPrompt.clear();
}
  • 调用方法
//! 添加遮罩
CMaskWidget* maskWidget = CMaskWidget::GetInstance();
maskWidget->setParent(this);
maskWidget->SetMainWidget(this);
maskWidget->SetDialogNames(QStringList() << "CBonusForNewUserDlg");
		
m_pDlgBonusForNewUser = new CBonusForNewUserDlg(this);
m_pDlgBonusForNewUser->installEventFilter(maskWidget);

其中,this指的是被遮盖的控件对象;m_pDlgBonusForNewUser指的是触发遮罩的控件对象,即m_pDlgBonusForNewUser一显示,就让遮罩弹出。

posted @ 2020-07-18 22:01  背叛的故里纸鹤  阅读(173)  评论(0)    收藏  举报