Qt 实现右下角消息通知队列

效果


下载地址

https://github.com/confidentFeng/QtAppProject

关键代码

NotifyWidget.cpp

// 显示下一条通知
void NotifyManager::showNext()
{
    // 如果通知数目超出限制,则显示"通知当前数目界面"
    if (m_notifyList.size() >= m_maxCount || m_dataQueue.isEmpty())
    {
        showQueueCount();
        return;
    }

    // 创建并显示新的通知框
    NotifyWidget *notifyWidget = new NotifyWidget(this); // 将管理员自身传给notifyWidget的m_manager
    m_notifyList.append(notifyWidget); // 添加到通知框列表
    notifyWidget->showArranged(m_notifyList.size()); // 设置新通知的显示位置
    notifyWidget->setData(m_dataQueue.dequeue()); // 设置数据队列的第一个数据(dequeue,删除队列第一个元素,并返回这个元素)
    showQueueCount(); // 显示队列的剩余通知数目

    // 通知过了displayTime时间之后隐藏之后销毁,然后触发下面槽函数
    connect(notifyWidget, &QObject::destroyed, this, [notifyWidget, this](){
        // 找到被销毁的通知在队列中的索引,然后移除该通知
        int index = m_notifyList.indexOf(notifyWidget);
        m_notifyList.removeAt(index);

        // 旧消息被移出后,就要显示通知队列中的下一个新消息,并排序
        for (; index<m_notifyList.size(); index++)
            m_notifyList[index]->showArranged(index+1);

        // 这里是为了实现周期提示功能,一般不用到,可以注释
        QTimer::singleShot(m_animateTime, this, [this](){
            showNext();
        });
    });
}

// 显示队列的剩余通知数目
void NotifyManager::showQueueCount()
{
    // 判断是否允许显示队列的剩余通知数目
    if (!m_isShowQueueCount)
        return;

    // 数据队列大于0,说明还有未显示的剩余通知,则显示数目;否则隐藏"剩余通知数目"
    if (!m_dataQueue.isEmpty())
    {
        m_notifyCount->showArranged(m_maxCount+1);
        m_notifyCount->setCount(m_dataQueue.size());
    }
    else {
        m_notifyCount->showArranged(0);
    }
}

// 根据通知在队列中的索引,来设置其的位置,相当于更新排序
void ArrangedWidget::showArranged(int posIndex)
{
    if (m_posIndex == posIndex)
        return;

    m_posIndex = posIndex;

    // 索引小于等于0,则隐藏
    if (posIndex <= 0)
    {
        // 如果已经隐藏,则返回
        if (!isVisible())
            return;

        // 隐藏动画
        propertyAnimationOnTarget(this, "windowOpacity", 0, m_manager->animateTime(), [this]() {
            this->hide();
            emit visibleChanged(false); // 隐藏信号
        });

        return;
    }

    // 计算提醒框的位置
    QSize wndsize = m_manager->notifyWndSize();
    QSize offset = QSize(wndsize.width(), wndsize.height()*posIndex + m_manager->spacing()*(posIndex-1));
    QPoint pos = m_manager->cornerPos() - QPoint(offset.width(), offset.height());

    // 如果原先是隐藏的,现在显示
    if (!isVisible())
    {
        this->show();
        this->move(pos);
        this->setWindowOpacity(0);
        propertyAnimationOnTarget(this, "windowOpacity", 1, m_manager->animateTime(), [this](){
            emit visibleChanged(true);
        });
    }
    else // 否则,移动位置
    {
        propertyAnimationOnTarget(this, "pos", pos, m_manager->animateTime());
    }
}

更多代码请下载源码查看。


参考:

每日一库之 Qt5-右下角消息通知 - 知乎 (zhihu.com)


posted @ 2022-12-14 16:17  fengMisaka  阅读(518)  评论(0编辑  收藏  举报