QQ界面模仿1
Posted 一只蚂蚁2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QQ界面模仿1相关的知识,希望对你有一定的参考价值。
大爱Qt!
QQ中点击联系人或群时,下面的面板是有动态效果的。一时兴起,来实现一下。
[TOC]
效果图
原理
其实实现的方法很多,这里我采用的是QPropertyAnimation。由于想重用代码,所以将动画效果封装在一个QWidget中。
基本思路:带封装的QWidget其实和QStackedWidget或QStackedLayout非常像,唯一不同的地方是在界面切换的时候需要增加动态效果。所以封装的接口也仿照QStackedWidget好了。
代码
class XWidgetAnimation : public QParallelAnimationGroup
Q_OBJECT
public:
XWidgetAnimation(QObject* parent = nullptr)
:QParallelAnimationGroup(parent)
m_posAnimation = createPropertyAnimation("pos");
m_posAnimation->setStartValue(QPoint(0, 0));
m_posAnimation->setEndValue(QPoint(0, 0));
m_sizeAnimation = createPropertyAnimation("size");
m_sizeAnimation->setStartValue(QSize(0, 0));
m_sizeAnimation->setEndValue(QSize(0, 0));
void setTargetObject(QWidget* target)
m_posAnimation->setTargetObject(target);
m_sizeAnimation->setTargetObject(target);
QWidget* targetObject()const return qobject_cast<QWidget*>( m_posAnimation->targetObject());
void setEndPos(const QPoint& pos) m_posAnimation->setEndValue(pos);
QPoint endPos()const return m_posAnimation->endValue().toPoint();
void setEndSize(const QSize& size) m_sizeAnimation->setEndValue(size);
QSize endSize()const return m_sizeAnimation->endValue().toSize();
QPoint startPos()const return m_posAnimation->startValue().toPoint();
QSize startSize()const return m_sizeAnimation->startValue().toSize();
void setDuration(int msecs)
m_posAnimation->setDuration(msecs);
m_sizeAnimation->setDuration(msecs);
private:
QPropertyAnimation* createPropertyAnimation(const QByteArray &propertyName)
QPropertyAnimation* animation = new QPropertyAnimation(this);
animation->setPropertyName(propertyName);
addAnimation(animation);
return animation;
void setStartPos(const QPoint& pos) m_posAnimation->setStartValue(pos);
void setStartSize(const QSize& size) m_sizeAnimation->setStartValue(size);
private:
QPropertyAnimation* m_posAnimation;
QPropertyAnimation* m_sizeAnimation;
friend class XAnimationWidget;
;
class XAnimationWidget : public QWidget
Q_OBJECT
public:
XAnimationWidget(QWidget* parent = nullptr)
:QWidget(parent),m_preWidget(nullptr), m_currentWidget(nullptr)
m_toTargetAnimation = new XWidgetAnimation(this);
m_fromTargetAnimation = new XWidgetAnimation(this);
m_fromTargetAnimation->setDirection(QAbstractAnimation::Backward);
connect(m_toTargetAnimation, SIGNAL(finished()), this, SLOT(onAnimationFinished()));
void addWidget(QWidget* widget)
Q_ASSERT(!m_widgets.contains(widget));
m_widgets.append(widget);
widget->setParent(this);
if (m_currentWidget)
widget->setVisible(false);
else
widget->move(0, 0);
widget->resize(this->size());
widget->setVisible(true);
m_currentWidget = widget;
void removeWidget(QWidget* widget)
m_widgets.removeOne(widget);
if (m_currentWidget == widget)
m_currentWidget = nullptr;
void insertWidget(int index, QWidget* widget) m_widgets.insert(index, widget);
int count()const return m_widgets.count();
int currentIndex()const return indexOf(m_currentWidget);
QWidget* currentWidget()const return m_currentWidget;
int indexOf(QWidget* widget)const return m_widgets.indexOf(widget);
QWidget* widget(int index)const return m_widgets.at(index);
XWidgetAnimation* fromTargetAnimation()const return m_fromTargetAnimation;
XWidgetAnimation* toTargetAnimation()const return m_toTargetAnimation;
public slots:
void setCurrentIndex(int index)
setCurrentWidget(widget(index));
void setCurrentWidget(QWidget* widget)
Q_ASSERT(m_widgets.contains(widget));
if (m_currentWidget == widget)
return;
m_preWidget = m_currentWidget;
m_currentWidget = widget;
preCurrentWidgetChangedEvent(m_preWidget, m_currentWidget);
m_toTargetAnimation->stop();
m_fromTargetAnimation->stop();
m_toTargetAnimation->setTargetObject(m_preWidget);
m_fromTargetAnimation->setTargetObject(m_currentWidget);
if (m_preWidget)
m_toTargetAnimation->start();
if (m_currentWidget)
m_fromTargetAnimation->start();
m_currentWidget->setVisible(true);
m_currentWidget->raise();
private slots:
void onAnimationFinished()
if (m_preWidget)
m_preWidget->setVisible(false);
protected:
virtual void resizeEvent(QResizeEvent *event)
m_toTargetAnimation->setStartSize(event->size());
m_fromTargetAnimation->setStartSize(event->size());
if (m_currentWidget)
m_currentWidget->resize(event->size());
virtual void preCurrentWidgetChangedEvent(QWidget* oldWidget, QWidget* newWidget)
private:
QList<QWidget*> m_widgets;
QWidget* m_preWidget;
QWidget* m_currentWidget;
XWidgetAnimation* m_toTargetAnimation;
XWidgetAnimation* m_fromTargetAnimation;
;
class MainPanelCenterWidget : public XAnimationWidget
Q_OBJECT
public:
MainPanelCenterWidget(QWidget* parent = nullptr)
:XAnimationWidget(parent)
protected:
virtual void resizeEvent(QResizeEvent *event)
XAnimationWidget::resizeEvent(event);
toTargetAnimation()->setEndSize(event->size());
fromTargetAnimation()->setEndSize(event->size());
virtual void preCurrentWidgetChangedEvent(QWidget* oldWidget, QWidget* newWidget)
int oldIndex = indexOf(oldWidget);
int newIndex = indexOf(newWidget);
int width = this->width();
if (oldIndex < newIndex)
toTargetAnimation()->setEndPos(QPoint(-width, 0));
fromTargetAnimation()->setEndPos(QPoint(width, 0));
else
toTargetAnimation()->setEndPos(QPoint(width, 0));
fromTargetAnimation()->setEndPos(QPoint(-width, 0));
;
以上是关于QQ界面模仿1的主要内容,如果未能解决你的问题,请参考以下文章
Fdog系列:使用Qt模仿QQ实现登录界面到主界面,功能篇。