当前位置:   article > 正文

Qt堆栈窗口stackwidget切换动画及叠加透明窗口_qt的qstackedwidget页面切换动画效果

qt的qstackedwidget页面切换动画效果


一、AnimateStackedWidget类

AnimateStackedWidget.cpp

#include "animatestackedwidget.h"

#include <QPropertyAnimation>
#include <QParallelAnimationGroup>
#include <QPixmap>

AnimateStackedWidget::AnimateStackedWidget(QWidget *parent) : QStackedWidget(parent)
{
    m_label = new QLabel(this);
    mform.installEventFilter(this);
    connect(&mform,&FloatForm::sig_btnClicked,this,[&](int idx){
        qDebug()<<"###############"<<idx;
        switchIndex(idx);
    });
}

void AnimateStackedWidget::switchIndex(int newIdx)
{
    int oldIdx = currentIndex();
    if (oldIdx == newIdx || newIdx < 0 || newIdx >= count())
    {
        return;
    }

    int w = this->width();
    int h = this->height();

    QPixmap pixmap = QPixmap::grabWindow(this->winId());
    m_label->setPixmap(pixmap);
    m_label->setGeometry(0, 0, w, h);
    m_label->show();

    setCurrentIndex(newIdx);

    QPropertyAnimation *animation1 = new QPropertyAnimation(m_label, "pos");
    QPropertyAnimation *animation2 = new QPropertyAnimation(currentWidget(), "pos");
    animation1->setDuration(500);
    animation2->setDuration(500);
    animation1->setEasingCurve(QEasingCurve::OutCubic);
    animation2->setEasingCurve(QEasingCurve::OutCubic);

    if (oldIdx < newIdx)  // 向左滑动
    {
        animation1->setStartValue(QPoint(0, 0));
        animation1->setEndValue(QPoint(0 - w, 0));
        animation2->setStartValue(QPoint(w, 0));
        animation2->setEndValue(QPoint(0, 0));
    }
    else  // 向右滑动
    {
        animation1->setStartValue(QPoint(0, 0));
        animation1->setEndValue(QPoint(w, 0));
        animation2->setStartValue(QPoint(0 - w, 0));
        animation2->setEndValue(QPoint(0, 0));
    }

    QParallelAnimationGroup *group = new QParallelAnimationGroup;
    group->addAnimation(animation1);
    group->addAnimation(animation2);
    group->start(QAbstractAnimation::DeleteWhenStopped);
    connect(group, SIGNAL(finished()), m_label, SLOT(hide()));
}

void AnimateStackedWidget::enterEvent(QEvent *event)
{
    qDebug()<<"AnimateStackedWidget::enterEvent";
    if (!mform.isVisible())
    {
        UpdateTransparentDialog();
        mform.show();
    }
}

void AnimateStackedWidget::leaveEvent(QEvent *event)
{
    qDebug()<<"AnimateStackedWidget::leaveEvent";
    if (mform.isVisible())
        mform.hide();
}
void AnimateStackedWidget::hideEvent(QHideEvent *event)
{
//    qDebug()<<"AnimateStackedWidget::hideEvent";
//    if (mform.isVisible())
//        mform.hide();
}

bool AnimateStackedWidget::eventFilter(QObject *watched, QEvent *event)
{
    return QStackedWidget::eventFilter(watched,event);
}

void AnimateStackedWidget::resizeEvent(QResizeEvent *event)
{
    UpdateTransparentDialog();
}
void AnimateStackedWidget::UpdateTransparentDialog()
{
    mform.resize(size());
    mform.move(mapToGlobal(QPoint(0, 0)));
}
void AnimateStackedWidget::paintEvent(QPaintEvent *event)
{
    UpdateTransparentDialog();
}

void AnimateStackedWidget::moveEvent(QMoveEvent *event)
{
    UpdateTransparentDialog();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

AnimateStackedWidget.h

#ifndef ANIMATESTACKEDWIDGET_H
#define ANIMATESTACKEDWIDGET_H

#include <QStackedWidget>
#include <QLabel>
#include <QDebug>
#include <QEvent>
#include "floatform.h"
class AnimateStackedWidget : public QStackedWidget
{
    Q_OBJECT
public:
    AnimateStackedWidget(QWidget *parent = NULL);

    void switchIndex(int newIdx);

private:
    QLabel *m_label;
    FloatForm mform;
protected:
    void enterEvent(QEvent* event);
    void leaveEvent(QEvent* event);
    void hideEvent(QHideEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);
    void resizeEvent(QResizeEvent* event);
    void paintEvent(QPaintEvent *event);
    void moveEvent(QMoveEvent *event);
private:
    void UpdateTransparentDialog();
};

#endif // ANIMATESTACKEDWIDGET_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

继承自QStackwidget,主要是切换窗口的switchIndex函数,通过QPropertyAnimation 属性动画来实现窗口的切换动画效果。

鼠标的进入和离开时间enterEvent和leaveEvent则是为了显示和隐藏透明层无边框窗口。

很多软件界面的图片定时翻页效果,和这个差不多大同小异,也可以这么实现,包括hover时暂停,左右箭头手动翻页等效果,都可以在这个基础上加以实现。

二、透明层类

FloatForm.cpp

#include "floatform.h"
#include "ui_floatform.h"

FloatForm::FloatForm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FloatForm)
{
    ui->setupUi(this);
    setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow | Qt::WindowStaysOnTopHint); // 设置无边框、子窗口
    setAttribute(Qt::WA_TranslucentBackground, true);       // 设置为透明窗口
//    setMouseTracking(true);
    mBtnGroup = new QButtonGroup(this);
    QList<QPushButton*> List = this->findChildren<QPushButton *>();
    for(int i =0;i< List.size();i++){
        mBtnGroup->addButton(List.at(i),i);
    }
    connect(mBtnGroup,static_cast<void(QButtonGroup::*)(int)>(&QButtonGroup::buttonClicked),[&](int id){
        emit sig_btnClicked(id);
    });
}

FloatForm::~FloatForm()
{
    delete ui;
}

void FloatForm::enterEvent(QEvent *e)
{
    Q_UNUSED(e)
    qDebug()<<"FloatForm::enterEvent";
    show();
}

void FloatForm::leaveEvent(QEvent *event)
{
     Q_UNUSED(event)
    qDebug()<<"FloatForm::leaveEvent";
    if (isVisible()) hide();
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

FloatForm.h

#ifndef FLOATFORM_H
#define FLOATFORM_H

#include <QWidget>
#include <QDebug>
#include <QEvent>
#include <QButtonGroup>
#include <QPropertyAnimation>
namespace Ui {
class FloatForm;
}

class FloatForm : public QWidget
{
    Q_OBJECT

public:
    explicit FloatForm(QWidget *parent = nullptr);
    ~FloatForm();

private:
    Ui::FloatForm *ui;
    QButtonGroup* mBtnGroup;
protected:
    void enterEvent(QEvent* e);
    void leaveEvent(QEvent *event);

signals:
    void sig_btnClicked(int id);
};

#endif // FLOATFORM_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

透明层窗口是作为上述动画statckwidget类的成员,重写了鼠标进入和离开事件,其他的也没什么

另外需要注意的是,窗口一定要设置透明属性:

setAttribute(Qt::WA_TranslucentBackground, true);
  • 1

还有一个要设置无边框:

setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow | Qt::WindowStaysOnTopHint); // 设置无边框、子窗口
  • 1

解释如下:

指示小部件应具有半透明背景,即,小部件的任何非不透明区域将是半透明的,因为小部件将具有alpha通道。设置此标志将导致设置WA_NOSYSTEMBACKGROUN。在Windows上,该小部件还需要设置Qt::FrameleSwindowHint窗口标志。此标志由小部件的作者设置或清除。

三、效果图

进入显示透明层,透明层只有5个按钮,如下:
  • 1

在这里插入图片描述

鼠标离开,隐藏,如下:
  • 1

在这里插入图片描述
点击切换,如下:
在这里插入图片描述


四、完整demo下载

demo下载
参考博文:https://gitee.com/zhouliqiu/animate-stacked-widget/tree/master

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/81550
推荐阅读
相关标签
  

闽ICP备14008679号