赞
踩
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(); }
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
继承自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(); }
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
透明层窗口是作为上述动画statckwidget类的成员,重写了鼠标进入和离开事件,其他的也没什么
另外需要注意的是,窗口一定要设置透明属性:
setAttribute(Qt::WA_TranslucentBackground, true);
还有一个要设置无边框:
setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow | Qt::WindowStaysOnTopHint); // 设置无边框、子窗口
解释如下:
指示小部件应具有半透明背景,即,小部件的任何非不透明区域将是半透明的,因为小部件将具有alpha通道。设置此标志将导致设置WA_NOSYSTEMBACKGROUN。在Windows上,该小部件还需要设置Qt::FrameleSwindowHint窗口标志。此标志由小部件的作者设置或清除。
进入显示透明层,透明层只有5个按钮,如下:
鼠标离开,隐藏,如下:
点击切换,如下:
demo下载
参考博文:https://gitee.com/zhouliqiu/animate-stacked-widget/tree/master
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。