Qt widget 伸缩动画效果

  分享一下我自己做的QT应用,这个应用还只是雏形很多功能并没有完成,但是关于界面的功能已经实现了许多,用麻雀虽小五脏俱全来形容挺合适。

感兴趣的可以下载源码:Commits · TTTTHBBBB/Coord (github.com)

 这个折叠的功能做的比较生硬,如果不用动画来显示右侧工具栏的弹出的话可能会更流畅,一个折叠功能分为两个widget,左侧是自定义的widget来实现点击时的动画效果,右侧的widget是工具栏,关于伸缩的效果我是使用QPropertyAnimation控制右侧工具栏的宽度,在父类的widget中重写paintEvent事件根据两个子类的宽度实时修正父类widget的宽度。

 关于圆形按钮,实际上是一个矩形区域,重写widget的mouseReleaseEvent,当按下时记录当前状态,同时执行与之相对应的动画效果。

 因为窗口的大小可能改变,所以需要实时计算widget的高度来获得正确的绘制参数。

关于动画效果的绘制思路 :
#include "collapsewidget.h"
#include "ui_collapsewidget.h"

CollapseWidget::CollapseWidget(QWidget *parent)
    : QFrame(parent)
    , ui(new Ui::CollapseWidget)
{
    ui->setupUi(this);
    this->initAnimation();
}

void CollapseWidget::initAnimation()
{
    //线段绘制动画
    m_showLineAnimation = new QPropertyAnimation(this,"showLine");
    m_showLineAnimation->setDuration(1000);
    m_showLineAnimation->setEasingCurve(QEasingCurve::InOutBack);

    //线段取消动画
    m_cancelLineAnimation = new QPropertyAnimation(this,"cancelLine");
    m_cancelLineAnimation->setDuration(1000);
    m_cancelLineAnimation->setEasingCurve(QEasingCurve::InOutBack);

    //样式绘制动画
    m_radiusAnimation = new QPropertyAnimation(this,"radius");
    m_radiusAnimation->setDuration(1000);
    m_radiusAnimation->setStartValue(0);
    m_radiusAnimation->setEndValue(qMax(height(),width())*2);
    m_radiusAnimation->setEasingCurve(QEasingCurve::InOutBack);

    //样式取消动画
    m_cancleRadiusAnimation = new QPropertyAnimation(this,"cancleRadius");
    m_cancleRadiusAnimation->setDuration(1000);
    m_cancleRadiusAnimation->setStartValue(qMax(height(),width())*2);
    m_cancleRadiusAnimation->setEndValue(0);
    m_cancleRadiusAnimation->setEasingCurve(QEasingCurve::InOutBack);

    TYPE = COLLSPSESTAUS::SYSTOLIC;
    ANIMATIONTYPE = STATUS::INITIALIZATION;

    connect(m_cancelLineAnimation, &QPropertyAnimation::finished, this, &CollapseWidget::drawDisplayAnimation);
    connect(m_cancleRadiusAnimation, &QPropertyAnimation::finished, this, &CollapseWidget::drawShowAnimation);

}

void CollapseWidget::drawShowAnimation()
{
    ANIMATIONTYPE = STATUS::LINESHOW;
    m_showLineAnimation->start();
    update();
}

void CollapseWidget::drawDisplayAnimation()
{
    ANIMATIONTYPE = STATUS::RADIUSSHOW;
    m_radiusAnimation->start();
    update();
}

void CollapseWidget::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);

    int parentwidth = width();
    int parentheight = height();
    int calibre = qMin(parentwidth, parentheight) - 10;

    // 计算画笔宽度
    int penWidth = 4; // 画笔宽度

    // 计算调整后的圆形矩形大小
    int adjustedCalibre = calibre - penWidth; // 减去画笔宽度的一半

    btnrect.setTopLeft(QPointF((parentwidth - adjustedCalibre) / 2, (parentheight - adjustedCalibre) / 2));
    btnrect.setBottomRight(QPointF((parentwidth + adjustedCalibre) / 2, (parentheight + adjustedCalibre) / 2));

    pointTop = QPoint(parentwidth / 2, (parentheight - adjustedCalibre) / 2 - penWidth/2 );
    pointBottom = QPoint(parentwidth / 2, (parentheight + adjustedCalibre) / 2 + penWidth/2);

    initLine = height()/2-adjustedCalibre/2-penWidth;

    //设置绘制线段
    m_showLineAnimation->setStartValue(0);
    m_showLineAnimation->setEndValue(height()/2-adjustedCalibre/2-penWidth);

    //设置取消线段
    m_cancelLineAnimation->setStartValue(height()/2-adjustedCalibre/2-penWidth);
    m_cancelLineAnimation->setEndValue(0);
}

void CollapseWidget::startAnimation()
{
    ANIMATIONTYPE = STATUS::RADIUSDISPLAY;
    m_cancleRadiusAnimation->start();
    update();
}

void CollapseWidget::displayAnimation()
{
    ANIMATIONTYPE = STATUS::LINEDISPLAY;
    m_cancelLineAnimation->start();
    update();
}

void CollapseWidget::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPen pen;
    pen.setStyle(Qt::SolidLine);
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    // 绘制样式
    pen.setWidth(3); // 调整样式画笔宽度
    pen.setColor(QColor(0, 170, 128));
    painter.setPen(pen);

    QPointF topCenter(width()/2,0);
    QPointF bottomCenter(width()/2,height());
    QPointF StarTopEllipse(pointTop);//上半区绘制
    QPointF CancleTopEllipse(pointTop);
    QPointF StartEllipse(pointBottom);//下半区绘制
    QPointF CancleEllips(pointBottom);

    if(ANIMATIONTYPE == STATUS::INITIALIZATION)
    {
        //上半区
        StarTopEllipse.setY(initLine);
        painter.drawLine(topCenter, StarTopEllipse);
        //下半区
        StartEllipse.setY(height()-initLine);
        painter.drawLine(StartEllipse,bottomCenter);
    }
    else if(ANIMATIONTYPE == STATUS::LINESHOW)
    {//创建
        //上半区
        StarTopEllipse.setY(showLine);
        painter.drawLine(topCenter, StarTopEllipse);
        //下半区
        StartEllipse.setY(height()-showLine);
        painter.drawLine(StartEllipse,bottomCenter);
    }
    else if(ANIMATIONTYPE == STATUS::LINEDISPLAY)
    {
        //上半区
        CancleTopEllipse.setY(cancelLine);
        painter.drawLine(topCenter, CancleTopEllipse);
        //下半区
        CancleEllips.setY(height()-cancelLine);
        painter.drawLine(CancleEllips,bottomCenter);
    }

    if(ANIMATIONTYPE == STATUS::RADIUSSHOW || ANIMATIONTYPE == STATUS::RADIUSDISPLAY)
    {
        qreal amendment = 0;
        ANIMATIONTYPE == STATUS::RADIUSSHOW ? amendment = radius : amendment = cancleRadius;

        painter.setPen(Qt::NoPen);
        painter.setBrush(QColor(64,65,66));
        painter.drawEllipse(QPointF(0,0), amendment, amendment);
        painter.drawEllipse(QPointF(width(),height()), amendment, amendment);
    }

    //绘制按钮
    pen.setWidth(4); // 画笔宽度
    pen.setColor(QColor(10, 238, 167));
    QBrush brush(QColor(0, 170, 128));
    painter.setBrush(brush);
    painter.setPen(pen);
    // 绘制圆形
    painter.drawEllipse(btnrect);

}

void CollapseWidget::mousePressEvent(QMouseEvent *event)
{
    m_pressPos = event->pos();
    update();
}

void CollapseWidget::mouseReleaseEvent(QMouseEvent * event)
{
    QPoint releasePos = event->pos();
    QPainterPath path;
    path.addEllipse(btnrect);

    if(path.contains(m_pressPos) && path.contains(releasePos))
    {
        if(TYPE == COLLSPSESTAUS::SYSTOLIC)
        {//当前状态是收缩,此时需要扩展
            displayAnimation();
            emit signal_btnClicked(COLLSPSESTAUS::EXPAND);
            TYPE = COLLSPSESTAUS::EXPAND;
        }else
        {
            startAnimation();
            emit signal_btnClicked(COLLSPSESTAUS::SYSTOLIC);
            TYPE = COLLSPSESTAUS::SYSTOLIC;
        }
    }
}

CollapseWidget::~CollapseWidget()
{
    delete ui;
}
伸缩动画代码
//实时调整父类的宽度
void CollapseAnimation::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    setFixedWidth(ui->FrameAnimation->width() + ui->widgetWork->width());
}
void CollapseAnimation::InitAnimation()
{
    ui->widgetWork->setFixedWidth(0);
    ui->widgetWork->setFrameStyle(QFrame::NoFrame);
    ui->FrameAnimation->setFrameStyle(QFrame::NoFrame);

    FrameWorkAnimation = new QPropertyAnimation(ui->widgetWork,"minimumWidth",this);
    FrameWorkAnimation->setDuration(2000);
    FrameWorkAnimation->setEasingCurve(QEasingCurve::OutCurve);

   ````
}

void CollapseAnimation::toggleFold(COLLSPSESTAUS type)
{
    if(type == COLLSPSESTAUS::EXPAND)
    {
        FrameWorkAnimation->setStartValue(0);
        FrameWorkAnimation->setEndValue(250);
    }
    else if(type == COLLSPSESTAUS::SYSTOLIC)
    {
        FrameWorkAnimation->setStartValue(250);
        FrameWorkAnimation->setEndValue(0);
    }
    FrameWorkAnimation->start();
}

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值