在日常项目中,界面布局上经常使用到侧边栏的方式,在侧边栏放置控件进行复合使用,可以实现子功能界面的弹出,效果展示如下:
界面控件很简单,主界面QWidget,侧边栏也用一个QWidget和一个按钮QPushbutton来进行组合。通过点击按钮来显示和隐藏侧边栏。主要用到的是控件的move()函数,配合QPropertyAnimation实现动画效果滑动显示隐藏。动画滑出动画效果使用到的是QPropertyAnimation类的setEasingCurve()函数,通过设置函数参数来实现不同的动画效果,具体效果可以通过Qt Create的帮助文件查询到。
实现方法:
1,首先UI主界面设计
可以看到我就是用了一个水平布局,布局里就放置浅红色和蓝色两个QWidget,然后浅红色的作为侧边栏(浅红色里面的布局不用管他,只是用来布局侧边栏里面的功能键),然后蓝色的不会去动他。
2,重写浅红色的QWidget的鼠标悬浮事件来控制窗口弹出
首先开启浅红色窗口的鼠标悬浮事件判断
ui->widget_side->setAttribute(Qt::WA_Hover, true);
在主窗口类里需要重写两个事件(待会再写具体实现),分别是
protected:
bool eventFilter(QObject* obj, QEvent* event);
void resizeEvent(QResizeEvent* event);
然后要给黄色侧边栏加载主窗口的事件,才能用到在主窗口类中重写的事件
ui->widget_side->installEventFilter(this);
重写事件,在事件中使用QPropertyAnimation来控制伸缩动画
在主窗口类中先声明一个私有变量QPropertyAnimation* propertyAnimation提供给事件调用。再声明一个布尔值bool sideFlag = true来表示当前侧边栏的伸缩状态。
在主窗口构造函数中初始化propertyAnimation:
m_propertyAnimation = new QPropertyAnimation(ui->widget_side, "geometry");
m_propertyAnimation->setEasingCurve(QEasingCurve::InOutQuint);
m_propertyAnimation->setDuration(200);
- 重写事件resizeEvent:
void MainWindow::resizeEvent(QResizeEvent *event)
{
width = ui->widget_side->width(); //width和height都是主窗口类的私有变量
height = ui->centralwidget->height();
m_propertyAnimation->setStartValue(QRect(-1, 0, 10, height)); //参数代表左,上,右,下坐标
m_propertyAnimation->setEndValue(QRect(-1, 0, width, height));
}
这一步是为了重新设置当前窗口下的伸缩的起点和重点位置坐标。这一步是难点:在布局下的widget的长度和宽度都是经过改变的,不在resize事件下重新获取widget的长度和宽度,只会得到最初始的无布局下的widget的长度和宽度,简单的说不是正确的数据,需要在resizeEvent下或者paintEvent下“在程序运行后”“延后地”获取widget的长度和宽度才是正确的尺寸数据。
- 重写事件eventFilter
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == ui->widget_side)
{
if (event->type() == QEvent::HoverEnter) //鼠标进入浅红色侧边栏中悬浮,正向播动画
{
m_propertyAnimation->setDirection(QAbstractAnimation::Forward);
m_propertyAnimation->start();
return true;
}
else if (event->type() == QEvent::HoverLeave) //鼠标离开浅红色侧边栏,反向播动画
{
m_propertyAnimation->setDirection(QAbstractAnimation::Backward);
m_propertyAnimation->start();
return false;
}
}
return QWidget::eventFilter(obj, event);
}