QT实现带动态弹出动画的自定义通知提示框
立即下载
资源介绍:
Qt中经常会用到提示框,用于交互操作!QMessageBox是被大多数人用到的,用起来是很方便,但是控件类型、大小、布局、样式、往往不是开发者想要的。本实例实现的Notification控件,是一种悬浮在角落的通知提醒框
#include "notification.h"
#include
#include
#include
#include
#include
#include
#include
static int nAppearTime = 200; // 出现的时间200ms
static int nDisappearTime = 200; // 消失的时间200ms
Notification::Notification(QObject *parent) : QObject(parent)
{
QWidget* pWidget = qobject_cast(parent);
if(pWidget == nullptr)
throw std::runtime_error("parent of notification error!");
m_size = pWidget->size();
m_vecItem.reserve(30);
}
Notification::~Notification()
{
}
void Notification::Push(NotifyType type, NotifyPosition pos, QString title, QString content, int nLive)
{
std::lock_guard lck(m_vecMtx);
NotificationItem* pItem = new NotificationItem(qobject_cast(parent()),
type,
pos,
title,
content,
nLive);
connect(pItem, &NotificationItem::itemRemoved, this, &Notification::itemRemoved);
int currentHeight = 0;
int currentX = 0;
if(pos == NotifyPosition::Pos_Top_Right)
{
currentX = m_size.width();
currentHeight = nMargin;
}
else if(pos == NotifyPosition::Pos_Top_Left)
{
currentX = -pItem->width();
currentHeight = nMargin;
}
else if(pos == NotifyPosition::Pos_Bottom_Left)
{
currentX = -pItem->width();
currentHeight = m_size.height() - nMargin - pItem->height();
}
else
{
currentX = m_size.width();
currentHeight = m_size.height() - nMargin - pItem->height();
}
for_each(m_vecItem.begin(), m_vecItem.end(), [&](NotificationItem* item) {
if(item->GetPosType() == pos)
{
if(pos == NotifyPosition::Pos_Top_Right)
{
currentHeight += (item->height() + nMargin);
}
else if(pos == NotifyPosition::Pos_Top_Left)
{
currentHeight += (item->height() + nMargin);
}
else if(pos == NotifyPosition::Pos_Bottom_Left)
{
currentHeight -= (item->height() + nMargin);
}
else
{
currentHeight -= (item->height() + nMargin);
}
}
});
pItem->move(currentX, currentHeight);
m_vecItem.emplace_back(pItem);
pItem->Show();
}
void Notification::itemRemoved(NotificationItem *pRemoved)
{
std::unique_lock lck(m_vecMtx);
int currentY = 0;
bool bFirst = true;
NotifyPosition pos = pRemoved->GetPosType();
for(auto itr = m_vecItem.begin(); itr != m_vecItem.end();)
{
if(*itr == pRemoved)
{
m_vecItem.erase(itr);
break;
}
else ++itr;
}
for_each(m_vecItem.begin(), m_vecItem.end(), [&, pos, bFirst, currentY](NotificationItem* item) mutable {
if(item->GetPosType() == pos)
{
if(bFirst)
{
if(pos == NotifyPosition::Pos_Top_Right)
{
currentY = nMargin;
}
else if(pos == NotifyPosition::Pos_Top_Left)
{
currentY = nMargin;
}
else if(pos == NotifyPosition::Pos_Bottom_Left)
{
currentY = m_size.height() - nMargin - item->height();
}
else
{
currentY = m_size.height() - nMargin - item->height();
}
bFirst = false;
}
else
{
if(item->IsAppearEnd())
{
if(pos == NotifyPosition::Pos_Top_Right)
{
currentY += (item->height() + nMargin);
}
else if(pos == NotifyPosition::Pos_Top_Left)
{
currentY += (item->height() + nMargin);
}
else if(pos == NotifyPosition::Pos_Bottom_Left)
{
currentY -= (item->height() + nMargin);
}
else
{
currentY -= (item->height() + nMargin);
}
}
}
if(item->IsAppearEnd())
{
QPropertyAnimation* pAnimation1 = new QPropertyAnimation(item, "geometry", this);
pAnimation1->setDuration(nDisappearTime);
pAnimation1->setStartValue(QRect(item->pos().x(),
item->pos().y(),
item->width(),
item->height()));
pAnimation1->setEndValue(QRect(item->pos().x(),
currentY,
item->width(),
item->height()));
pAnimation1->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped);
}
}
});
}
///////////////////////////////////////////////////////////////
NotificationItem::NotificationItem(QWidget *parent,
NotifyType type,
NotifyPosition pos,
QString title,
QString content,
int nLife) : QWidget(parent),
m_enPos(pos),
m_bAppearEnd(false)
{
setObjectName(QStringLiteral("notification_item"));
QLabel* pTitle = new QLabel(title, this);
pTitle->setObjectName(QStringLiteral("label_title"));
NotificationLabel* pContent = new NotificationLabel(this, nFixedWidth - 10, content);
QFont font;
font.setPointSize(11);
font.setFamily(QStringLiteral("Microsoft Yahei"));
pContent->setFont(font);
QPushButton* pClose = new QPushButton(this);
pClose->setFixedSize(16, 16);
pClose->setObjectName(QStringLiteral("btn_close"));
pClose->setCursor(QCursor(Qt::PointingHandCursor));
setStyleSheet(QStringLiteral("QWidget#notification_item{border:none;border-radius:8px;background-color:white;}"
"QLabel#label_title{border:none;background-color:white;font-family:Microsoft Yahei;font-size:20px;font-weight:700;color:#303133;}"
"QPushButton#btn_close{border:none;background-color:white;background-position:center;border-image:url(:/skin/notification_close.png);}"
"QPushButton:hover#btn_close{border-image:url(:/skin/notification_close_hover.png);}"));
// 标题设置
pTitle->setAlignment(Qt::AlignLeft | Qt::AlignTop);
QFontMetrics fontWidth(pTitle->font());
QString elideNote = fontWidth.elidedText(pTitle->text(),
Qt::ElideRight,
120);
pTitle->setText(elideNote);
pTitle->setToolTip(title);
pTitle->adjustSize();
// 内容设置
pContent->Adjust();
// 布局
if(type != NotifyType::Notify_Type_None)
{
QLabel* pIcon = new QLabel(this);
pIcon->setStyleSheet(QStringLiteral("QLabel{border:none;background-color:white;}"));
if(type == NotifyType::Notify_Type_Success)
{
pIcon->setPixmap(QPixmap(":/skin/type_success.png"));
}
else if(type == NotifyType::Notify_Type_Error)
{
pIcon->setPixmap(QPixmap(":/s