使用QT实现一个自定义的ToolBox,做了一个展开和收缩的动画效果,目前是500ms延时,基于之前的代码做了些修改,参考了已写其它资料,目前测试效果还算良好,不过是demo版,使用需要自己移植和改造,上代码:
AnimationToolBox.h
#include <QWidget>
#include <QMap>
#include "publiclibrary.h"
class QLayout;
class QScrollArea;
class AnimationToolPage;
class PLUGINSSHARED_EXPORT AnimationToolBox : public QWidget
{
Q_OBJECT
public:
explicit AnimationToolBox(QWidget *parent = nullptr);
AnimationToolBox(const QString &name, QWidget *parent = NULL);
virtual ~AnimationToolBox();
void addWidget(const QString &title, QWidget *widget);
void setActions(const QStringList &titleList);
signals:
public slots:
private:
void initialize();
private:
QString m_strToolBoxName;
QMap<QString, AnimationToolPage*> m_mapToolPage;
QScrollArea *m_scrollArea;
QLayout *m_layout;
Qt::Orientations m_ori;
};
AnimationToolBox.cpp
#include "animationtoolbox.h"
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include "animationtoolpage.h"
AnimationToolBox::AnimationToolBox(QWidget *parent)
: QWidget(parent)
, m_strToolBoxName("")
, m_ori(Qt::Vertical)
{
initialize();
}
AnimationToolBox::AnimationToolBox(const QString &name, QWidget *parent)
: QWidget(parent)
, m_strToolBoxName(name)
, m_ori(Qt::Vertical)
{
initialize();
}
AnimationToolBox::~AnimationToolBox()
{
}
void AnimationToolBox::addWidget(const QString &title, QWidget *widget)
{
AnimationToolPage *page = NULL;
if(m_mapToolPage.contains(title))
{
page = m_mapToolPage.value(title);
}
if(NULL == page)
{
page = new AnimationToolPage(title, this);
}
page->setMinimumHeight(40);
page->addPage(title, widget);
m_layout->addWidget(page);
}
void AnimationToolBox::setActions(const QStringList &titleList)
{
foreach (QString title, titleList)
{
addWidget(title, new QWidget);
}
}
void AnimationToolBox::initialize()
{
QGridLayout *gridLayout = new QGridLayout(this);
gridLayout->setSpacing(0);
gridLayout->setObjectName(QStringLiteral("gridLayout"));
gridLayout->setContentsMargins(0, 0, 0, 0);
m_scrollArea = new QScrollArea(this);
m_scrollArea->setObjectName(QStringLiteral("scrollArea"));
m_scrollArea->setWidgetResizable(true);
QWidget *widget = new QWidget(this);
if(m_ori == Qt::Vertical) //暂时只实现垂直布局
{
m_layout = new QVBoxLayout;
}
else
{
m_layout = new QHBoxLayout;
}
m_layout->setContentsMargins(0, 0, 0, 0);
m_layout->setSpacing(0);
QVBoxLayout *vBoxLayout = new QVBoxLayout(widget);
vBoxLayout->setContentsMargins(0, 0, 0, 0);
vBoxLayout->addLayout(m_layout);
vBoxLayout->addStretch(1);
m_scrollArea->setWidget(widget);
gridLayout->addWidget(m_scrollArea, 0, 0, 1, 1);
}
AnimationToolPage.h
#include <QWidget>
class QStackedWidget;
class AnimationToolPage : public QWidget
{
Q_OBJECT
Q_PROPERTY(int fixValue READ fixValue WRITE setFixValue/* NOTIFY fixHeightChanged*/)
public:
explicit AnimationToolPage(QWidget *parent = nullptr);
AnimationToolPage(const QString &name, QWidget *parent = NULL);
virtual ~AnimationToolPage();
void addPage(const QString &name, QWidget *page);
int fixValue() const;
void setFixValue(const int &value);
//signals:
public slots:
void slotBtnClicked(const QString& name, const int&type, const int&state);
private:
void initialize();
private:
QString m_strName;
QString m_childName;
QWidget *m_childWidget;
QWidget *m_pButton;
Qt::Orientations m_ori;
QStackedWidget *m_contantWidget;
int m_nFixHeight;
int m_nMaxHeight;
};
AnimationToolPage.cpp
此文件做了些修改,上个版本,折叠会button会闪,改造了一下,目前测试还算ok,需要横向的需要自己手动增加了
#include "animationtoolpage.h"
#include "button/checkboxlabelbutton.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QStackedWidget>
#include <QPropertyAnimation>
#include "publicdefine.h"
AnimationToolPage::AnimationToolPage(QWidget *parent)
: QWidget(parent)
, m_strName("toolpage")
, m_childName("")
, m_childWidget(NULL)
, m_pButton(NULL)
, m_contantWidget(NULL)
, m_nFixHeight(0)
, m_nMaxHeight(200)
, m_ori(Qt::Vertical)
{
initialize();
}
AnimationToolPage::AnimationToolPage(const QString &name, QWidget *parent)
: QWidget(parent)
, m_strName(name)
, m_childName("")
, m_childWidget(NULL)
, m_pButton(NULL)
, m_contantWidget(NULL)
, m_nFixHeight(0)
, m_nMaxHeight(200)
, m_ori(Qt::Vertical)
{
initialize();
}
AnimationToolPage::~AnimationToolPage()
{
}
void AnimationToolPage::addPage(const QString &name, QWidget *page)
{
m_childName = name;
if(NULL == page)
{
SAFE_DELETE(m_contantWidget);
return;
}
m_nMaxHeight = page->height();
m_contantWidget->addWidget(page);
}
int AnimationToolPage::fixValue() const
{
return m_nFixHeight;
}
void AnimationToolPage::setFixValue(const int &value)
{
m_nFixHeight = value;
if(Qt::Vertical == m_ori)
{
this->setFixedHeight(value);
}
else
{
this->setFixedWidth(value);
}
}
void AnimationToolPage::slotBtnClicked(const QString &name, const int &type, const int &state)
{
//复选框(暂时不实现)
if(type == CheckBoxLabelButton::CheckBox)
{
return;
}
//创建动画
QPropertyAnimation *pAnimation = new QPropertyAnimation(this, "fixValue");
pAnimation->setDuration(500);
bool bHide = false;
if(state == CheckBoxLabelButton::Collapse)//折叠
{
bHide = true;
pAnimation->setStartValue(m_nMaxHeight);
pAnimation->setEndValue(40);
}
else//展开
{
m_contantWidget->show();
pAnimation->setStartValue(40);
pAnimation->setEndValue(m_nMaxHeight);
}
pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
if(bHide)
{
connect(pAnimation, &QPropertyAnimation::finished, [=](){
m_contantWidget->hide();
});
}
}
void AnimationToolPage::initialize()
{
if(NULL == m_pButton)
{
CheckBoxLabelButton *pBtn = new CheckBoxLabelButton(m_strName, this);
pBtn->setMinimumHeight(40);
pBtn->setBtnName(m_strName, CheckBoxLabelButton::Button);
pBtn->setHidden();
connect(pBtn, &CheckBoxLabelButton::sigBtnClicked,
this, &AnimationToolPage::slotBtnClicked);
m_pButton = pBtn;
pBtn->setStyleSheet("background-color:rgb(128,128,128);");
}
if(!m_contantWidget)
{
m_contantWidget = new QStackedWidget(this);
}
//目前仅实现垂直方向
QVBoxLayout *vLayout = new QVBoxLayout(this);
vLayout->setSpacing(0);
vLayout->setContentsMargins(0, 0, 0, 0);
vLayout->addWidget(m_pButton);
vLayout->addWidget(m_contantWidget);
this->setLayout(vLayout);
this->setFixedHeight(40);
m_contantWidget->hide();
}
应用:
AnimationToolBox *pToolBox = new AnimationToolBox(this);
QLabel *pLabel = new QLabel("test");
pLabel->setStyleSheet("background-color:rgb(255,255,255)");
pToolBox->addWidget("test", pLabel);
pLabel = new QLabel("test1");
pLabel->setStyleSheet("background-color:rgb(255,255,255)");
pToolBox->addWidget("test1", pLabel);
ui->verticalLayout->addWidget(pToolBox);
还有一个button的代码就没粘贴了,就是实现一个button,点击信号判断是折叠还是展开就可以了