QT 滑屏窗口管理器
Qt记述之路 _01
文章目录
前言
在我们QT使用过程中通常会遇到这样的场景(界面显示空间有限,而我们又需要显示很多内容),通常我们会使用到QTabWidget或者多个QWidget的 hide() 和 show()以及QStackedWidget窗口管理器, 来实现多窗口显示和管理,当然这些方法都能够很好的解决我们的问题,但是在美观和交互上就差了一些。而本博客就采用了QStackedWidget和QPropertyAnimation,以及QPainter实现了一个完美的模仿平板手机的滑动窗口管理。
一、功能
1.滑动翻页(模仿手机,平板)
2.点击切换页面
3.显示页标签
4.实现接口(方便使用)
5.封装为动态库
20220407_163925
二、QStackedWidget是什么?
QStackedWidget类提供了一组小部件,其中每次只显示一个小部件,QStackedWidget可以用来创建一个类似于QTabWidget提供的用户界面。 它是一个方便的布局小部件,构建在qstackkedlayout类的顶部。 像qstackkedlayout一样,qstackkedwidget可以被构造和填充一些子部件(“页面”):
/*====================== QStackedWidget 使用 =======================*/
QWidget *firstPageWidget = new QWidget;
QWidget *secondPageWidget = new QWidget;
QWidget *thirdPageWidget = new QWidget;
QStackedWidget *stackedWidget = new QStackedWidget;
stackedWidget->addWidget(firstPageWidget);
stackedWidget->addWidget(secondPageWidget);
stackedWidget->addWidget(thirdPageWidget);
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(stackedWidget);
setLayout(layout);
/*=================================================================*/
三、那么正文来了!!!
1.事件处理
判断鼠标点击和移动事件(需要考虑误触碰、拖拽时间、是否翻页):
// 事件过滤器
bool PageWidget::eventFilter(QObject *obj, QEvent *evt)
{
QMouseEvent *mouse = static_cast<QMouseEvent *>(evt);
// 计算参数
int _width = this->width(); // 计算边框大小
if(m_Widgets && m_Widgets->count() > 0 && mouse && m_PriorAnimation && m_PriorAnimation->state() == QAbstractAnimation::Stopped)
{
if(mouse->type()==QEvent::MouseButtonPress)
{
m_pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch(); // 记录按下的时间
press_x = mouse->globalX();
press_y = mouse->globalY();
}
else if(mouse->type()==QEvent::MouseButtonRelease)
{
if((QDateTime::currentDateTime().toMSecsSinceEpoch() - m_pressMSec) > 300 && qAbs(mouse->globalX() - press_x) < _width / 3)
e_SwitchFlag = SWITCH_NONE;
if(qAbs(press_x - mouse->globalX()) > 3)
SmoothAnimationStart();
}
else if(mouse->type()==QEvent::MouseMove)
{
m_MovePoint = mouse->globalPos();
// 判断向左还是向右滑(并且还有±5的防止误触限制)
if(press_x - mouse->globalX() < -5)
{
e_SwitchFlag = SWITCH_PRE;
if(m_Widgets->currentIndex() - 1 >= 0)
m_LastWidget = m_Widgets->widget(m_Widgets->currentIndex() - 1);
else
m_LastWidget = nullptr;
}
else if(press_x - mouse->globalX() > 5)
{
e_SwitchFlag = SWITCH_NEXT;
if(m_Widgets->currentIndex() + 1 < m_Widgets->count())
m_LastWidget = m_Widgets->widget(m_Widgets->currentIndex() + 1);
else
m_LastWidget = nullptr;
}
else
{
e_SwitchFlag = SWITCH_NONE;
m_LastWidget = nullptr;
}
// 移动位置
SmoothMove();
}
}
return QWidget::eventFilter(obj,evt);
}
2.标签绘制
// 绘制标签
void LabelPage::DrawLabel(QPainter &painter)
{
if(PageWidgetSumIndex <= 1)
return;
// 计算参数
int _ypos;
painter.setRenderHint(QPainter::Antialiasing,true);
for(int i = 0; i < PageWidgetSumIndex; i++)
{
if(i == PageWidgetCurrentIndex)
painter.setBrush(m_LabelColor);
else
painter.setBrush(QColor(220,220,220,150));
if(Label_Dot == e_style)
{
m_Length = 10;
m_movedistance = 8;
_ypos = m_Length/2;
painter.drawEllipse(QPointF(m_Length/2 + (i*m_movedistance) + (i*m_Length), _ypos),m_Length/2,m_Length/2);
}
else if(Label_Bar_Type == e_style)
{
m_Length = 30;
m_movedistance = 5;
_ypos = m_Length/2;
painter.drawRoundedRect(QRectF((i*m_movedistance) + (i*m_Length), _ypos, m_Length, m_Length/7),m_Length/12, m_Length/12);
}
}
m_sumlength = PageWidgetSumIndex * m_Length + (PageWidgetSumIndex-1) * m_movedistance;
if(Label_Dot == e_style)
move(m_size.width()/2 - m_sumlength/2, m_size.height() - (m_Length * 3.5));
else if(Label_Bar_Type == e_style)
move(m_size.width()/2 - m_sumlength/2, m_size.height() - (m_Length * 1.5));
resize(m_sumlength, m_Length);
}
总结
实现逻辑就是用QStackedWidget来管理我们的窗口,用QPropertyAnimation(动画类)来实现翻页效果,便签页就用Qpainter绘制(注意:这里面会出现一个问题,就是绘制的标签会被窗口挡住,这个时候就可以用一个新的QWidget来绘制标签,然后把这个QWidget置顶就OK!),纯属拙见,欢迎大家指教…