Qt设置弹出窗口背景阴影效果

通过MaskWidget来实现,原理如下:

1. 设置要遮挡的窗体(一般是主窗口);

2. 设置目标窗口,并绑定该窗口的显示事件,一旦目标显示,阴影窗口就显示;反则同样;

3.完成阴影效果。

据观察存在一定问题,目标窗口的父窗口问题,任务栏会有两个窗口图标如

image

直接插入代码:

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 */)
{
  setOpacity(0.4);
  setBgColor(QColor(0, 0, 0));
  setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
  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);
posted @ 2020-03-05 14:07  lily8561  阅读(1534)  评论(0)    收藏  举报