QT 实现滑动页面切换一

发布于:2024-10-17 ⋅ 阅读:(11) ⋅ 点赞:(0)

1.界面实现效果

以下是具体的项目需要用到的效果展示。
在这里插入图片描述

2.简介

原理:使用Qt的QPropertyAnimation动画类,这里简单来说就是切换两个界面。
这个widget里面可以放很多个待切换的界面,每次切换的时候将当前界面和切换后的界面显示,其他界面都隐藏,然后当前界面移动到主界面之外,下一个界面移动到主界面里面。,当然这两个界面需要一起移动,不然滑动的中间会存在缝隙,就不美观。
以下是demo展示,原理都一样,只是中间的界面不一样而已,可以自定义。
在这里插入图片描述
中间定义的滚动CustomWidget类

#include <QWidget>
#include <QPropertyAnimation>
#include <QObject> 

class CustomWidget : public QWidget
{
	Q_OBJECT
public:
    CustomWidget(QWidget *parent);
    ~CustomWidget();
 
public:
    //数量
    int count() const;
    //当前显示的界面索引
    int currentIndex() const;
    //添加widget(任何widget都可以),返回索引值
    int addWidget(QWidget *widget);
    //索引
    int indexOf(QWidget *widget) const;
    //插入,返回索引值
    int insertWidget(int index, QWidget *widget);
    //当前widget
    QWidget *currentWidget() const;
    QWidget *widget(int index) const;
    //删除
    void removeWidget(QWidget *widget);
    //设置动画时间
    void setDuration(int duration);
 
signals:
	void currentChanged(int index);
	void widgetRemoved(int index);
 
public slots:
	void setCurrentIndex(int index);
	void setCurrentWidget(QWidget *widget);
 
private slots:
	void onValueChanged(const QVariant &);
 
private:
	void moveAnimationStart();
	void setWidgetsVisible();
 
protected:
	void resizeEvent(QResizeEvent *event);
 
private:
    int m_offset = 0;
    int m_curIndex = 0;
    int m_lastIndex = 0;
 
    int m_duration = 500;
    QPropertyAnimation *m_moveAnimation = nullptr;
	QList<QWidget *> m_widgetLst;
};

#include "CustomWidget.h"
#include <QPropertyAnimation>
 
CustomWidget::CustomWidget(QWidget *parent)
	: QWidget(parent)
{
	m_moveAnimation = new QPropertyAnimation(this, "");
	m_moveAnimation->setDuration(m_duration);
    connect(m_moveAnimation, &QPropertyAnimation::valueChanged, this, &CustomWidget::onValueChanged);
}
 
CustomWidget::~CustomWidget()
{
 
}
 
int CustomWidget::count() const
{
	return m_widgetLst.size();
}
 
int CustomWidget::currentIndex() const
{
	return m_curIndex;
}
 
void CustomWidget::setDuration(int duration)
{
	m_duration = duration;
}
 
int CustomWidget::addWidget(QWidget * widget)
{
	int index = indexOf(widget);
	if (index >= 0){
		return index;
	}
	widget->setParent(this);
	m_widgetLst.append(widget);
	return count() - 1;
}
 
int CustomWidget::indexOf(QWidget * widget) const
{
	return m_widgetLst.indexOf(widget);
}
 
int CustomWidget::insertWidget(int index, QWidget * widget)
{
	int curindex = indexOf(widget);
	if (curindex >= 0) {
		return curindex;
	}
	widget->setParent(this);
	m_widgetLst.insert(index, widget);
	return index;
}
 
QWidget * CustomWidget::currentWidget() const
{
	if (m_curIndex >= 0 && m_curIndex < count()){
		return m_widgetLst.at(m_curIndex);
	}
    return 0;
}
 
QWidget * CustomWidget::widget(int index) const
{
	if (index >= 0 && index < count()) {
		return m_widgetLst.at(index);
	}
    return 0;
}
 
void CustomWidget::removeWidget(QWidget * widget)
{
	int index = indexOf(widget);
	if (index >= 0) {
		m_widgetLst.removeAll(widget);
		emit widgetRemoved(index);
	}
}
 
void CustomWidget::setCurrentWidget(QWidget * widget)
{
	int index = indexOf(widget);
	if (index >= 0 && m_curIndex != index) {
		setCurrentIndex(index);
	}
}
 
void CustomWidget::setCurrentIndex(int index)
{
	if (index >= 0 && m_curIndex != index) {
		m_lastIndex = m_curIndex;
		m_curIndex = index;	
		moveAnimationStart();
		emit currentChanged(index);
	}
}
 
void CustomWidget::resizeEvent(QResizeEvent *event)
{
	QWidget::resizeEvent(event);
 
	int size = count();
	for (int i = 0; i < size; i++) {
		m_widgetLst.at(i)->resize(this->width(), this->height());
	}
 
	if (m_moveAnimation->state() == QAbstractAnimation::Running) {
		moveAnimationStart();
	}
	else {
		setWidgetsVisible();
        onValueChanged(0);
	}
}
 
void CustomWidget::onValueChanged(const QVariant &value)
{
	if (m_widgetLst.size() == 0)
		return;
	m_offset = value.toInt();
	m_widgetLst.at(m_curIndex)->move(m_offset, 0);
	if (m_curIndex > m_lastIndex) {
		m_widgetLst.at(m_lastIndex)->move(m_offset - this->width(), 0);
    } else if (m_curIndex < m_lastIndex){
		m_widgetLst.at(m_lastIndex)->move(this->width() + m_offset, 0);
	}
}
 
void CustomWidget::moveAnimationStart()
{
	m_moveAnimation->stop();
	setWidgetsVisible();
	int startOffset = m_offset;
	if (m_curIndex > m_lastIndex) {
		if (startOffset == 0) startOffset = this->width();
		else startOffset = this->width() - qAbs(startOffset);
	}
	else {
		if (startOffset == 0) startOffset = -this->width();
		else startOffset = qAbs(startOffset) - this->width();
	}
	m_moveAnimation->setDuration(qAbs(startOffset) * m_duration / this->width());
	m_moveAnimation->setStartValue(startOffset);
	m_moveAnimation->setEndValue(0);
	m_moveAnimation->start();
}
 
void CustomWidget::setWidgetsVisible()
{
	int size = count();
	for (int i = 0; i < size; i++) {
		if (m_lastIndex == i || m_curIndex == i)
			m_widgetLst.at(i)->setVisible(true);
		else {
			m_widgetLst.at(i)->setVisible(false);
		}
	}
}

以下是示例CustomExampleWidget类(可以换成自己的widget)
在这里插入图片描述

3.使用

以下是mainwidget中,提升一下CustomWidget。
在这里插入图片描述

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_btnLeft_clicked();

    void on_btnRight_clicked();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H

#include "widget.h"
#include "ui_widget.h"
#include "CustomExampleWidget.h"

unsigned int num = 0;

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    QString num1[6] = {"1","2","3","4","5","6"};
    QString num2[6] = {"11","12","13","14","15","16"};
    QString num3[6] = {"21","22","23","24","25","26"};
    QString num4[6] = {"31","32","33","34","35","36"};

    int index = 0;
    CustomExampleWidget *widget1 = new CustomExampleWidget(ui->widget);
    widget1->setInfo(num1);
    index = ui->widget->addWidget(widget1);

    CustomExampleWidget *widget2 = new CustomExampleWidget(ui->widget);
    widget2->setInfo(num2);
    index = ui->widget->addWidget(widget2);

    CustomExampleWidget *widget3 = new CustomExampleWidget(ui->widget);
    widget3->setInfo(num3);
    index = ui->widget->addWidget(widget3);

    CustomExampleWidget *widget4 = new CustomExampleWidget(ui->widget);
    widget4->setInfo(num4);
    index = ui->widget->addWidget(widget4);

}

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

void Widget::on_btnLeft_clicked()
{
    num--;
    if(num<0)
        num = 0;
    ui->widget->setCurrentIndex(num);
}

void Widget::on_btnRight_clicked()
{
    num++;
    if(num > ui->widget->count()-1)
        num = ui->widget->count()-1;
    ui->widget->setCurrentIndex(num);
}