分享一下我自己做的QT应用,这个应用还只是雏形很多功能并没有完成,但是关于界面的功能已经实现了许多,用麻雀虽小五脏俱全来形容挺合适。
感兴趣的可以下载源码:Commits · TTTTHBBBB/Coord (github.com);
这个折叠的功能做的比较生硬,如果不用动画来显示右侧工具栏的弹出的话可能会更流畅,一个折叠功能分为两个widget,左侧是自定义的widget来实现点击时的动画效果,右侧的widget是工具栏,关于伸缩的效果我是使用QPropertyAnimation控制右侧工具栏的宽度,在父类的widget中重写paintEvent事件根据两个子类的宽度实时修正父类widget的宽度。
关于圆形按钮,实际上是一个矩形区域,重写widget的mouseReleaseEvent,当按下时记录当前状态,同时执行与之相对应的动画效果。
因为窗口的大小可能改变,所以需要实时计算widget的高度来获得正确的绘制参数。
关于动画效果的绘制思路 :![](https://i-blog.csdnimg.cn/direct/19c306d5b5c648beadd7fbb0399d0a51.jpeg)
#include "collapsewidget.h"
#include "ui_collapsewidget.h"
CollapseWidget::CollapseWidget(QWidget *parent)
: QFrame(parent)
, ui(new Ui::CollapseWidget)
{
ui->setupUi(this);
this->initAnimation();
}
void CollapseWidget::initAnimation()
{
//线段绘制动画
m_showLineAnimation = new QPropertyAnimation(this,"showLine");
m_showLineAnimation->setDuration(1000);
m_showLineAnimation->setEasingCurve(QEasingCurve::InOutBack);
//线段取消动画
m_cancelLineAnimation = new QPropertyAnimation(this,"cancelLine");
m_cancelLineAnimation->setDuration(1000);
m_cancelLineAnimation->setEasingCurve(QEasingCurve::InOutBack);
//样式绘制动画
m_radiusAnimation = new QPropertyAnimation(this,"radius");
m_radiusAnimation->setDuration(1000);
m_radiusAnimation->setStartValue(0);
m_radiusAnimation->setEndValue(qMax(height(),width())*2);
m_radiusAnimation->setEasingCurve(QEasingCurve::InOutBack);
//样式取消动画
m_cancleRadiusAnimation = new QPropertyAnimation(this,"cancleRadius");
m_cancleRadiusAnimation->setDuration(1000);
m_cancleRadiusAnimation->setStartValue(qMax(height(),width())*2);
m_cancleRadiusAnimation->setEndValue(0);
m_cancleRadiusAnimation->setEasingCurve(QEasingCurve::InOutBack);
TYPE = COLLSPSESTAUS::SYSTOLIC;
ANIMATIONTYPE = STATUS::INITIALIZATION;
connect(m_cancelLineAnimation, &QPropertyAnimation::finished, this, &CollapseWidget::drawDisplayAnimation);
connect(m_cancleRadiusAnimation, &QPropertyAnimation::finished, this, &CollapseWidget::drawShowAnimation);
}
void CollapseWidget::drawShowAnimation()
{
ANIMATIONTYPE = STATUS::LINESHOW;
m_showLineAnimation->start();
update();
}
void CollapseWidget::drawDisplayAnimation()
{
ANIMATIONTYPE = STATUS::RADIUSSHOW;
m_radiusAnimation->start();
update();
}
void CollapseWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
int parentwidth = width();
int parentheight = height();
int calibre = qMin(parentwidth, parentheight) - 10;
// 计算画笔宽度
int penWidth = 4; // 画笔宽度
// 计算调整后的圆形矩形大小
int adjustedCalibre = calibre - penWidth; // 减去画笔宽度的一半
btnrect.setTopLeft(QPointF((parentwidth - adjustedCalibre) / 2, (parentheight - adjustedCalibre) / 2));
btnrect.setBottomRight(QPointF((parentwidth + adjustedCalibre) / 2, (parentheight + adjustedCalibre) / 2));
pointTop = QPoint(parentwidth / 2, (parentheight - adjustedCalibre) / 2 - penWidth/2 );
pointBottom = QPoint(parentwidth / 2, (parentheight + adjustedCalibre) / 2 + penWidth/2);
initLine = height()/2-adjustedCalibre/2-penWidth;
//设置绘制线段
m_showLineAnimation->setStartValue(0);
m_showLineAnimation->setEndValue(height()/2-adjustedCalibre/2-penWidth);
//设置取消线段
m_cancelLineAnimation->setStartValue(height()/2-adjustedCalibre/2-penWidth);
m_cancelLineAnimation->setEndValue(0);
}
void CollapseWidget::startAnimation()
{
ANIMATIONTYPE = STATUS::RADIUSDISPLAY;
m_cancleRadiusAnimation->start();
update();
}
void CollapseWidget::displayAnimation()
{
ANIMATIONTYPE = STATUS::LINEDISPLAY;
m_cancelLineAnimation->start();
update();
}
void CollapseWidget::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QPen pen;
pen.setStyle(Qt::SolidLine);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制样式
pen.setWidth(3); // 调整样式画笔宽度
pen.setColor(QColor(0, 170, 128));
painter.setPen(pen);
QPointF topCenter(width()/2,0);
QPointF bottomCenter(width()/2,height());
QPointF StarTopEllipse(pointTop);//上半区绘制
QPointF CancleTopEllipse(pointTop);
QPointF StartEllipse(pointBottom);//下半区绘制
QPointF CancleEllips(pointBottom);
if(ANIMATIONTYPE == STATUS::INITIALIZATION)
{
//上半区
StarTopEllipse.setY(initLine);
painter.drawLine(topCenter, StarTopEllipse);
//下半区
StartEllipse.setY(height()-initLine);
painter.drawLine(StartEllipse,bottomCenter);
}
else if(ANIMATIONTYPE == STATUS::LINESHOW)
{//创建
//上半区
StarTopEllipse.setY(showLine);
painter.drawLine(topCenter, StarTopEllipse);
//下半区
StartEllipse.setY(height()-showLine);
painter.drawLine(StartEllipse,bottomCenter);
}
else if(ANIMATIONTYPE == STATUS::LINEDISPLAY)
{
//上半区
CancleTopEllipse.setY(cancelLine);
painter.drawLine(topCenter, CancleTopEllipse);
//下半区
CancleEllips.setY(height()-cancelLine);
painter.drawLine(CancleEllips,bottomCenter);
}
if(ANIMATIONTYPE == STATUS::RADIUSSHOW || ANIMATIONTYPE == STATUS::RADIUSDISPLAY)
{
qreal amendment = 0;
ANIMATIONTYPE == STATUS::RADIUSSHOW ? amendment = radius : amendment = cancleRadius;
painter.setPen(Qt::NoPen);
painter.setBrush(QColor(64,65,66));
painter.drawEllipse(QPointF(0,0), amendment, amendment);
painter.drawEllipse(QPointF(width(),height()), amendment, amendment);
}
//绘制按钮
pen.setWidth(4); // 画笔宽度
pen.setColor(QColor(10, 238, 167));
QBrush brush(QColor(0, 170, 128));
painter.setBrush(brush);
painter.setPen(pen);
// 绘制圆形
painter.drawEllipse(btnrect);
}
void CollapseWidget::mousePressEvent(QMouseEvent *event)
{
m_pressPos = event->pos();
update();
}
void CollapseWidget::mouseReleaseEvent(QMouseEvent * event)
{
QPoint releasePos = event->pos();
QPainterPath path;
path.addEllipse(btnrect);
if(path.contains(m_pressPos) && path.contains(releasePos))
{
if(TYPE == COLLSPSESTAUS::SYSTOLIC)
{//当前状态是收缩,此时需要扩展
displayAnimation();
emit signal_btnClicked(COLLSPSESTAUS::EXPAND);
TYPE = COLLSPSESTAUS::EXPAND;
}else
{
startAnimation();
emit signal_btnClicked(COLLSPSESTAUS::SYSTOLIC);
TYPE = COLLSPSESTAUS::SYSTOLIC;
}
}
}
CollapseWidget::~CollapseWidget()
{
delete ui;
}
伸缩动画代码
//实时调整父类的宽度
void CollapseAnimation::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
setFixedWidth(ui->FrameAnimation->width() + ui->widgetWork->width());
}
void CollapseAnimation::InitAnimation()
{
ui->widgetWork->setFixedWidth(0);
ui->widgetWork->setFrameStyle(QFrame::NoFrame);
ui->FrameAnimation->setFrameStyle(QFrame::NoFrame);
FrameWorkAnimation = new QPropertyAnimation(ui->widgetWork,"minimumWidth",this);
FrameWorkAnimation->setDuration(2000);
FrameWorkAnimation->setEasingCurve(QEasingCurve::OutCurve);
````
}
void CollapseAnimation::toggleFold(COLLSPSESTAUS type)
{
if(type == COLLSPSESTAUS::EXPAND)
{
FrameWorkAnimation->setStartValue(0);
FrameWorkAnimation->setEndValue(250);
}
else if(type == COLLSPSESTAUS::SYSTOLIC)
{
FrameWorkAnimation->setStartValue(250);
FrameWorkAnimation->setEndValue(0);
}
FrameWorkAnimation->start();
}