Qt QSnackBar自定义提示弹窗

        提示弹窗在GUI中比较常用的有QMessageBox或自定义Widget,但是这些会挡住当前页面并且要手动关闭,非常不方便,于是本文介绍了一种不阻塞线程的弹窗动画,可以自动消失

        主要逻辑为自定义一个按钮,通过动画来实现上下移动,根据字符长度改变按钮的大小

1.自定义一个MySnackBar类,通过qt动画来实现

MySnackBar.h

#ifndef MYSNACKBAR_H
#define MYSNACKBAR_H

#include <QWidget>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QSequentialAnimationGroup>
#include <QGraphicsOpacityEffect>
#include <QPushButton>

class MySnackbar : public QWidget
{
    Q_OBJECT

public:
    MySnackbar(QWidget *parent = nullptr);
    ~MySnackbar();

    void initAnimation();
    void setSnackbarStyleSheet(const  QString & message_str);
    void setDuration(int stay_time);//500ms

public slots:
    void showMessage(const  QString & message_str,int y=0);
    void showMessage(const  QString & message_str, bool isSucc,int y=0);

private:
    QParallelAnimationGroup *m_group;
    QPushButton *m_pbtn_ptr;

    QPropertyAnimation *pPos_start_Animation ;
    QPauseAnimation *pPause_Animation;
    QPropertyAnimation *pPos_back_Animation;
    QSequentialAnimationGroup *pPosGroup ;

private:
    QWidget *parent_widget;
};
#endif // MYSNACKBAR_H

2.初始化动画 

void MySnackbar::initAnimation() {

    int snack_width = 200;     // 计算按钮的宽度
    int snack_height = 70;  // 计算按钮的高度

    setWindowFlags(Qt::FramelessWindowHint);  // 设置窗口为无边框

    // 上升动画
    pPos_start_Animation = new QPropertyAnimation(this, "pos");  // 创建位置属性动画对象
    pPos_start_Animation->setDuration(500);  // 500毫秒
    pPos_start_Animation->setEasingCurve(QEasingCurve::InOutQuad);  // 设置动画缓动曲线

    // 悬停动画
    pPause_Animation = new QPauseAnimation(1000);  // 创建暂停动画对象,持续时间为1000毫秒

    // 下降动画
    pPos_back_Animation = new QPropertyAnimation(this, "pos");  // 创建位置属性动画对象
    pPos_back_Animation->setDuration(500);  // 500毫秒
    pPos_back_Animation->setEasingCurve(QEasingCurve::InOutQuad);  // 设置动画缓动曲线

    pPosGroup = new QSequentialAnimationGroup(this);  // 创建顺序动画组对象
    // pPosGroup->addPause(500);  // 可选的暂停动画,暂停时间为500毫秒
    pPosGroup->addAnimation(pPos_start_Animation);  // 将上升动画添加到顺序动画组
    pPosGroup->addAnimation(pPause_Animation);  // 将悬停动画添加到顺序动画组
    pPosGroup->addAnimation(pPos_back_Animation);  // 将下降动画添加到顺序动画组

    m_group = new QParallelAnimationGroup(this);  // 创建并行动画组对象
    m_group->addAnimation(pPosGroup);  // 将顺序动画组添加到并行动画组

    m_pbtn_ptr = new QPushButton(this);  // 创建按钮对象
    m_pbtn_ptr->setFixedSize(snack_width - 10, snack_height);  // 设置按钮大小
    QHBoxLayout* box_ptr = new QHBoxLayout(this);  // 创建水平布局对象
    box_ptr->setContentsMargins(0,0,0,0);  // 设置布局边距
    box_ptr->addWidget(m_pbtn_ptr);  // 将按钮添加到布局中

    // 动画结束后隐藏控件
    connect(m_group, &QParallelAnimationGroup::finished, this, [this]() {
        this->hide();  // 隐藏控件
    });
}

3.封装设置样式以及动画延时时间的函数

void MySnackbar::setSnackbarStyleSheet(const QString& message_str) { m_pbtn_ptr->setStyleSheet(message_str); }

void MySnackbar::setDuration(int stay_time) { pPause_Animation->setDuration(stay_time); }

4. 显示动画,根据字符长度,动态改变弹窗的大小

void MySnackbar::showMessage(const QString& message_str,int y) {
    m_group->stop();
    m_pbtn_ptr->setText(message_str);
    int str_size = (message_str.size() *7);//根据字符串长度动态调整
    if (parent_widget) {
        QRect parentGeometry = parent_widget->geometry();  // 获取父窗口的位置和大小
        int parentWidth = parentGeometry.width();          // 获取父窗口的宽度
        int parentHeight = parentGeometry.height();        // 获取父窗口的高度

        int snack_width = 200;     // 按钮的宽度
        int snack_height = 70;  // 按钮的高度

        this->setFixedSize(snack_width + str_size, snack_height);
        m_pbtn_ptr->setFixedSize(snack_width - 10 + str_size, snack_height - 10);
        QFont font = m_pbtn_ptr->font();
        int fontSize = m_pbtn_ptr->font().pointSize()*newAdjFontScale;
        if(fontSize>0) font.setPointSize(fontSize);

        m_pbtn_ptr->setFont(font);

        int start_x = (parentWidth - this->width()) / 2;
        int start_y = parentHeight-y;

        pPos_start_Animation->setStartValue(QPoint(start_x, start_y));
        pPos_start_Animation->setEndValue(QPoint(start_x, start_y - this->height()));

        pPos_back_Animation->setStartValue(QPoint(start_x, start_y - this->height()));
        pPos_back_Animation->setEndValue(QPoint(start_x, start_y));
        this->move(start_x, start_y);

        show();
        m_group->setDirection(QAbstractAnimation::Forward);  // 设置动画播放方向为正向
        m_group->setLoopCount(1);  // 设置动画循环次数为1次
        m_group->start();  // 启动动画
    }
}

5.封装一个接口方便使用

void MySnackbar::showMessage(const QString &message_str, bool isSucc,int y)
{
    if (isSucc)
        setSnackbarStyleSheet("QPushButton{background-color:rgb(85,188,179);color:white;border-radius:10px;font-family:Microsoft YaHei;font:bold 18px;}");
    else
        setSnackbarStyleSheet("QPushButton{background-color:rgb(255,0,0);color:white;border-radius:10px;font-family:Microsoft YaHei;font:bold 18px;}");

    showMessage(message_str,y);
}

 6.使用方法以及效果

snackBar = new MySnackbar(this);
snackBar->showMessage(msg, isSucc);

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值