Qt滚动日期选择器
Qt滚动日期选择器最近产品经理提了一个需求,要实现一个滚动日期选择器。这个功能看似简单,实际实现起来不容易,里面有一些细节需要注意。目前网上很难找到类似的控件,只能找到单独的一条控件这意味着又要开始造轮子了 ( ・᷄д・᷅ )我先实现了单条的纵向控件,分别实现年、月、日独自的上下拖拽,最后把它们整合在一起。代码比较繁琐,不够优雅,不过功能还是实现了的 ✌ ・︵・年份滚动条rollingboxy.h
·
Qt滚动日期选择器
最近产品经理提了一个需求,要实现一个滚动日期选择器。这个功能看似简单,实际实现起来不容易,里面有一些细节需要注意。
目前网上很难找到类似的控件,只能找到单独的一条控件
这意味着又要开始造轮子了 ( ・᷄д・᷅ )
我先实现了单条的纵向控件,分别实现年、月、日独自的上下拖拽,最后把它们整合在一起。代码比较繁琐,不够优雅,不过功能还是实现了的 ✌ ・︵・
年份滚动条
rollingboxy.h
//时间滚动条-年份
#ifndef ROLLINGBOXY_H
#define ROLLINGBOXY_H
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QTimer>
#include <QDateTime>
class RollingBoxY : public QWidget
{
Q_OBJECT
Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation)
public:
explicit RollingBoxY(QWidget *parent = 0);
void setRange(int min,int max); //设置范围
int y_value;
public slots:
int readValue(); //获取当前值
private:
QTimer *r_time;
protected:
int m_minRange;
int m_maxRange;
int m_currentValueY = QDateTime::currentDateTime().toString("yyyy").toInt();
bool isDragging;
int m_deviation;
int m_mouseSrcPos;
int m_numSize;//计算所得的数字字符尺寸,以最长的情况为准
QPropertyAnimation *homingAni;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
// void wheelEvent(QWheelEvent *);
void paintEvent(QPaintEvent *);
void paintNum(QPainter &painter,int num,int deviation); //绘制数字
void homing(); //使选中的数字回到屏幕中间
int readDeviation(); //获取鼠标移动偏移量,默认为0
void setDeviation(int n); //设置偏移量
signals:
void currentValueChanged(int value); //当前数值改变信号
void deviationChange(float deviation); //偏移量改变信号
int sendYear(int);
};
#endif // ROLLINGBOXY_H
rollingboxy.cpp
//时间滚动条-年份
#include <rollingboxy.h>
#include <QTimer>
RollingBoxY::RollingBoxY(QWidget *parent) :
QWidget(parent),
m_minRange(1950), //最小值
m_maxRange(2050), //最大值
// m_currentValueY(2020), //当前选中的值
isDragging(0), //鼠标是否按下
m_deviation(0), //偏移量,记录鼠标按下后移动的垂直距离
m_numSize(6) //计算所得的数字字符尺寸,以最长的情况为准
{
this -> setWindowFlags(windowFlags() &~Qt::WindowMinMaxButtonsHint);
this -> setStyleSheet("background:white;");
homingAni = new QPropertyAnimation(this,"deviation"); //一个控制动画效果的类
homingAni->setDuration(300); //设置动画持续时间
homingAni->setEasingCurve(QEasingCurve::OutQuad); //设置动画的缓动曲线,这里OutQuad是二次函数缓和曲线,减速到零
}
//设置范围
void RollingBoxY::setRange(int min,int max)
{
m_minRange = min;
m_maxRange = max;
if(m_currentValueY < min) //如果选中的当前值小于最小值,就等于最小值
m_currentValueY = min;
if(m_currentValueY > max) //最大值同理
m_currentValueY = max;
//计算字符尺寸
m_numSize = 3;
int temp = m_maxRange;
while(temp > 0)
{
temp /= 10;
m_numSize++;
}
repaint(); //重绘此组件,需要进行重绘时,要使用repaint
}
//获取当前值
int RollingBoxY::readValue()
{
return m_currentValueY;
}
//鼠标按下事件
void RollingBoxY::mousePressEvent(QMouseEvent *e)
{
homingAni->stop(); //动画停止
isDragging = 1; //鼠标是否按下的标志位,布尔类型
m_mouseSrcPos = e->pos().y(); //鼠标按下时候的y轴坐标记录下来
}
//鼠标移动事件
void RollingBoxY::mouseMoveEvent(QMouseEvent *e)
{
if(isDragging)
{
//数值到边界时,阻止继续往对应方向移动
if((m_currentValueY == m_minRange && e->pos().y() >= m_mouseSrcPos)||
(m_currentValueY == m_maxRange && e->pos().y() <= m_mouseSrcPos))
return;
m_deviation = e->pos().y() - m_mouseSrcPos; //垂直偏移量 = 现在的坐标 - 开始的坐标
//若移动速度过快时进行限制
if(m_deviation > (height()-1)/4)
m_deviation = (height()-1)/4;
else if(m_deviation < -(height()-1)/4)
m_deviation = -(height()-1)/4;
emit deviationChange((float)m_deviation/((height()-1)/5)); //发出偏移量改变的信号,随着偏移量改变,重绘数字,就变成了数字滚动的效果
repaint();
}
}
//鼠标松开事件
void RollingBoxY::mouseReleaseEvent(QMouseEvent *)
{
if(isDragging) //如果鼠标松开了,那么还原鼠标按下标志位
{
isDragging = 0;
homing(); //使选中的数字回到屏幕中间
}
}
//void RollingBoxM::wheelEvent(QWheelEvent *e)
//{
// if(e->delta()>0)
// {
// m_deviation = (this->height() -1)/4;
// }
// else{
// m_deviation = -(this->height() -1)/4;
// }
// homing();
// repaint();
//}
//绘图事件
void RollingBoxY::paintEvent(QPaintEvent *)
{
QPainter painter(this); //创建画家类,指定绘图设备
painter.setRenderHint(QPainter::Antialiasing, true); //抗锯齿
int Width = width()-1;
int Height = height()-1;
if(m_deviation >= Height/4 && m_currentValueY > m_minRange) //偏移量大于1/4的时候,数字减一
{
m_mouseSrcPos += Height/4; //鼠标起始位置重新设置,即加上1/4的高度
m_deviation -= Height/4; //偏移量重新设置,即减去1/4的高度
m_currentValueY -= 1;
}
if(m_deviation <= -Height/4 && m_currentValueY < m_maxRange) //同理,数字加一
{
m_mouseSrcPos -= Height/4;
m_deviation += Height/4;
m_currentValueY += 1;
}
//中间数字
paintNum(painter,m_currentValueY,m_deviation); //将选中数字画到中间
//两侧数字1
if(m_currentValueY != m_minRange) //选中的数字不是最小,不是最大,那么就有两侧数字,然后画出两侧数字
paintNum(painter,m_currentValueY-1,m_deviation-Height/4);
if(m_currentValueY != m_maxRange)
paintNum(painter,m_currentValueY+1,m_deviation+Height/4);
//两侧数字2,超出则不显示
if(m_deviation >= 0 && m_currentValueY-2 >= m_minRange)
paintNum(painter,m_currentValueY-2,m_deviation-Height/2);
if(m_deviation <= 0 && m_currentValueY+2 <= m_maxRange)
paintNum(painter,m_currentValueY+2,m_deviation+Height/2);
//中间数字两侧的边框
painter.setPen(QPen(QColor(70,144,249),2));
painter.drawLine(0,Height/8*3,Width,Height/8*3);
painter.drawLine(0,Height/8*5,Width,Height/8*5);
}
//画数字
void RollingBoxY::paintNum(QPainter &painter,int num,int deviation)
{
int Width = this->width()-1;
int Height = this->height()-1;
int size = (Height - qAbs(deviation))/m_numSize; //qAbs 返回输入参数对应类型的绝对值
int transparency = 255-510*qAbs(deviation)/Height; //设置透明度
int height = Height/2-3*qAbs(deviation)/5;
int y = Height/2+deviation-height/2;
QFont font;
font.setPixelSize(size); //设置像素大小
painter.setFont(font); //设置字体
painter.setPen(QColor(0,0,0,transparency)); //设置画笔
painter.drawText(QRectF(0,y,Width,height), //画文本,参数:QRectF参数:位置xy,长宽大小;对齐方式,居中对齐;内容
Qt::AlignCenter,
(QString::number(num)+tr("年")));
}
void RollingBoxY::homing()
{
//将数字矫正到中心
if(m_deviation > height()/8)
{
homingAni->setStartValue((height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValueY--;
}
else if(m_deviation > -height()/8)
{
homingAni->setStartValue(m_deviation);
homingAni->setEndValue(0);
}
else if(m_deviation < -height()/8)
{
homingAni->setStartValue(-(height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValueY++;
}
emit currentValueChanged(m_currentValueY); //发送当前数值改变信号
homingAni->start(); //开始动画
}
//获取鼠标移动偏移量
int RollingBoxY::readDeviation()
{
return m_deviation;
}
//设置偏移量
void RollingBoxY::setDeviation(int n)
{
m_deviation = n;
repaint();
}
月份滚动条
rollingboxm.h
//时间滚动条-月份
#ifndef ROLLINGBOXM_H
#define ROLLINGBOXM_H
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QTimer>
#include <QDateTime>
class RollingBoxM : public QWidget
{
Q_OBJECT
Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation)
public:
explicit RollingBoxM(QWidget *parent = 0);
void setRange(int min,int max); //设置范围
public slots:
int readValue(); //获取当前值
private:
QTimer *time;
protected:
int m_minRange;
int m_maxRange;
int m_currentValueM = QDateTime::currentDateTime().toString("MM").toInt();
bool isDragging;
int m_deviation;
int m_mouseSrcPos;
int m_numSize;//计算所得的数字字符尺寸,以最长的情况为准
QPropertyAnimation *homingAni;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
// void wheelEvent(QWheelEvent *);
void paintEvent(QPaintEvent *);
void paintNum(QPainter &painter,int num,int deviation); //绘制数字
void homing(); //使选中的数字回到屏幕中间
int readDeviation(); //获取鼠标移动偏移量,默认为0
void setDeviation(int n); //设置偏移量
signals:
void currentValueChanged(int value); //当前数值改变信号
void deviationChange(float deviation); //偏移量改变信号
int sendMonth(int);
};
#endif // ROLLINGBOXM_H
rollingboxm.cpp
//时间滚动条-月份
#include <rollingboxm.h>
#include <QTimer>
RollingBoxM::RollingBoxM(QWidget *parent) :
QWidget(parent),
m_minRange(1), //最小值
m_maxRange(12), //最大值
// m_currentValueM(10), //
isDragging(0), //鼠标是否按下
m_deviation(0), //偏移量,记录鼠标按下后移动的垂直距离
m_numSize(6) //计算所得的数字字符尺寸,以最长的情况为准
{
this -> setWindowFlags(windowFlags() &~Qt::WindowMinMaxButtonsHint);
this -> setStyleSheet("background:white;");
homingAni = new QPropertyAnimation(this,"deviation"); //一个控制动画效果的类
homingAni->setDuration(300); //设置动画持续时间
homingAni->setEasingCurve(QEasingCurve::OutQuad); //设置动画的缓动曲线,这里OutQuad是二次函数缓和曲线,减速到零
}
//设置范围
void RollingBoxM::setRange(int min,int max)
{
m_minRange = min;
m_maxRange = max;
if(m_currentValueM < min) //如果选中的当前值小于最小值,就等于最小值
m_currentValueM = min;
if(m_currentValueM > max) //最大值同理
m_currentValueM = max;
//计算字符尺寸
m_numSize = 3;
int temp = m_maxRange;
while(temp > 0)
{
temp /= 10;
m_numSize++;
}
repaint(); //重绘此组件,需要进行重绘时,要使用repaint
}
//获取当前值
int RollingBoxM::readValue()
{
return m_currentValueM;
}
//鼠标按下事件
void RollingBoxM::mousePressEvent(QMouseEvent *e)
{
homingAni->stop(); //动画停止
isDragging = 1; //鼠标是否按下的标志位,布尔类型
m_mouseSrcPos = e->pos().y(); //鼠标按下时候的y轴坐标记录下来
}
//鼠标移动事件
void RollingBoxM::mouseMoveEvent(QMouseEvent *e)
{
if(isDragging)
{
//数值到边界时,阻止继续往对应方向移动
if((m_currentValueM == m_minRange && e->pos().y() >= m_mouseSrcPos)||
(m_currentValueM == m_maxRange && e->pos().y() <= m_mouseSrcPos))
return;
m_deviation = e->pos().y() - m_mouseSrcPos; //垂直偏移量 = 现在的坐标 - 开始的坐标
//若移动速度过快时进行限制
if(m_deviation > (height()-1)/4)
m_deviation = (height()-1)/4;
else if(m_deviation < -(height()-1)/4)
m_deviation = -(height()-1)/4;
emit deviationChange((float)m_deviation/((height()-1)/5)); //发出偏移量改变的信号,随着偏移量改变,重绘数字,就变成了数字滚动的效果
repaint();
}
}
//鼠标松开事件
void RollingBoxM::mouseReleaseEvent(QMouseEvent *)
{
if(isDragging) //如果鼠标松开了,那么还原鼠标按下标志位
{
isDragging = 0;
homing(); //使选中的数字回到屏幕中间
}
}
//void RollingBoxM::wheelEvent(QWheelEvent *e)
//{
// if(e->delta()>0)
// {
// m_deviation = (this->height() -1)/4;
// }
// else{
// m_deviation = -(this->height() -1)/4;
// }
// homing();
// repaint();
//}
//绘图事件
void RollingBoxM::paintEvent(QPaintEvent *)
{
QPainter painter(this); //创建画家类,指定绘图设备
painter.setRenderHint(QPainter::Antialiasing, true); //抗锯齿
int Width = width()-1;
int Height = height()-1;
if(m_deviation >= Height/4 && m_currentValueM > m_minRange) //偏移量大于1/4的时候,数字减一
{
m_mouseSrcPos += Height/4; //鼠标起始位置重新设置,即加上1/4的高度
m_deviation -= Height/4; //偏移量重新设置,即减去1/4的高度
m_currentValueM -= 1;
}
if(m_deviation <= -Height/4 && m_currentValueM < m_maxRange) //同理,数字加一
{
m_mouseSrcPos -= Height/4;
m_deviation += Height/4;
m_currentValueM += 1;
}
//中间数字
paintNum(painter,m_currentValueM,m_deviation); //将选中数字画到中间
//两侧数字1
if(m_currentValueM != m_minRange) //选中的数字不是最小,不是最大,那么就有两侧数字,然后画出两侧数字
paintNum(painter,m_currentValueM-1,m_deviation-Height/4);
if(m_currentValueM != m_maxRange)
paintNum(painter,m_currentValueM+1,m_deviation+Height/4);
//两侧数字2,超出则不显示
if(m_deviation >= 0 && m_currentValueM-2 >= m_minRange)
paintNum(painter,m_currentValueM-2,m_deviation-Height/2);
if(m_deviation <= 0 && m_currentValueM+2 <= m_maxRange)
paintNum(painter,m_currentValueM+2,m_deviation+Height/2);
//中间数字两侧的边框
painter.setPen(QPen(QColor(70,144,249),2));
painter.drawLine(0,Height/8*3,Width,Height/8*3);
painter.drawLine(0,Height/8*5,Width,Height/8*5);
}
//画数字
void RollingBoxM::paintNum(QPainter &painter,int num,int deviation)
{
int Width = this->width()-1;
int Height = this->height()-1;
int size = (Height - qAbs(deviation))/m_numSize; //qAbs 返回输入参数对应类型的绝对值
int transparency = 255-510*qAbs(deviation)/Height; //设置透明度
int height = Height/2-3*qAbs(deviation)/5;
int y = Height/2+deviation-height/2;
QFont font;
font.setPixelSize(size); //设置像素大小
painter.setFont(font); //设置字体
painter.setPen(QColor(0,0,0,transparency)); //设置画笔
painter.drawText(QRectF(0,y,Width,height), //画文本,参数:QRectF参数:位置xy,长宽大小;对齐方式,居中对齐;内容
Qt::AlignCenter,
(QString::number(num)+tr("月")));
}
void RollingBoxM::homing()
{
//将数字矫正到中心
if(m_deviation > height()/8)
{
homingAni->setStartValue((height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValueM--;
}
else if(m_deviation > -height()/8)
{
homingAni->setStartValue(m_deviation);
homingAni->setEndValue(0);
}
else if(m_deviation < -height()/8)
{
homingAni->setStartValue(-(height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValueM++;
}
emit currentValueChanged(m_currentValueM); //发送当前数值改变信号
homingAni->start(); //开始动画
}
//获取鼠标移动偏移量
int RollingBoxM::readDeviation()
{
return m_deviation;
}
//设置偏移量
void RollingBoxM::setDeviation(int n)
{
m_deviation = n;
repaint();
}
日期滚动条
rollingboxd.h
//时间滚动条-日期
#ifndef ROLLINGBOXD_H
#define ROLLINGBOXD_H
#include <QTimer>
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QDateTime>
#include <rollingboxy.h>
#include <rollingboxm.h>
class RollingBoxD : public QWidget
{
Q_OBJECT
Q_PROPERTY(int deviation READ readDeviation WRITE setDeviation)
public:
explicit RollingBoxD(QWidget *parent = 0);
// void setRange(int min,int max); //设置范围
int readValue(); //获取当前值
void setRange(int min,int max); //设置范围
public slots:
// void receiveValue();
private:
int m_currYear;
int m_currMonth;
QTimer *time;
RollingBoxY *rby;
RollingBoxM *rbm;
protected:
int m_minRange;
int m_maxRange;
int m_currentValue = QDateTime::currentDateTime().toString("dd").toInt();
bool isDragging;
int m_deviation;
int m_mouseSrcPos;
int m_numSize;//计算所得的数字字符尺寸,以最长的情况为准
QPropertyAnimation *homingAni;
void mousePressEvent(QMouseEvent *);
void mouseMoveEvent(QMouseEvent *);
void mouseReleaseEvent(QMouseEvent *);
// void wheelEvent(QWheelEvent *);
void paintEvent(QPaintEvent *);
void paintNum(QPainter &painter,int num,int deviation); //绘制数字
void homing(); //使选中的数字回到屏幕中间
int readDeviation(); //获取鼠标移动偏移量,默认为0
void setDeviation(int n); //设置偏移量
int maxValue();
signals:
void currentValueChanged(int value); //当前数值改变信号
void deviationChange(float deviation); //偏移量改变信号
};
#endif // ROLLINGBOXD_H
rollingboxd.cpp
//时间滚动条-日期
#include <QTimer>
#include <QDialog>
#include <rollingboxd.h>
RollingBoxD::RollingBoxD(QWidget *parent) :
QWidget(parent),
m_minRange(1), //最小值
// m_currentValue(20), //当前选中的值
isDragging(0), //鼠标是否按下
m_deviation(0), //偏移量,记录鼠标按下后移动的垂直距离
m_numSize(6) //计算所得的数字字符尺寸,以最长的情况为准
{
this -> setWindowFlags(windowFlags() &~Qt::WindowMinMaxButtonsHint);
this -> setStyleSheet("background:white;");
homingAni = new QPropertyAnimation(this,"deviation"); //一个控制动画效果的类
homingAni->setDuration(300); //设置动画持续时间
homingAni->setEasingCurve(QEasingCurve::OutQuad); //设置动画的缓动曲线,这里OutQuad是二次函数缓和曲线,减速到零
}
//设置范围
void RollingBoxD::setRange(int min,int max)
{
m_minRange = min;
m_maxRange = max;
if(m_currentValue < min) //如果选中的当前值小于最小值,就等于最小值
m_currentValue = min;
if(m_currentValue > max) //最大值同理
m_currentValue = max;
//计算字符尺寸
m_numSize = 3;
int temp = m_maxRange;
while(temp > 0)
{
temp /= 10;
m_numSize++;
}
repaint(); //重绘此组件,需要进行重绘时,要使用repaint
}
//获取当前值
int RollingBoxD::readValue()
{
return m_currentValue;
}
//鼠标按下事件
void RollingBoxD::mousePressEvent(QMouseEvent *e)
{
homingAni->stop(); //动画停止
isDragging = 1; //鼠标是否按下的标志位,布尔类型
m_mouseSrcPos = e->pos().y(); //鼠标按下时候的y轴坐标记录下来
}
//鼠标移动事件
void RollingBoxD::mouseMoveEvent(QMouseEvent *e)
{
if(isDragging)
{
//数值到边界时,阻止继续往对应方向移动
if((m_currentValue == m_minRange && e->pos().y() >= m_mouseSrcPos)||
(m_currentValue == m_maxRange && e->pos().y() <= m_mouseSrcPos))
return;
m_deviation = e->pos().y() - m_mouseSrcPos; //垂直偏移量 = 现在的坐标 - 开始的坐标
//若移动速度过快时进行限制
if(m_deviation > (height()-1)/4)
m_deviation = (height()-1)/4;
else if(m_deviation < -(height()-1)/4)
m_deviation = -(height()-1)/4;
emit deviationChange((float)m_deviation/((height()-1)/5)); //发出偏移量改变的信号,随着偏移量改变,重绘数字,就变成了数字滚动的效果
repaint();
}
}
//鼠标松开事件
void RollingBoxD::mouseReleaseEvent(QMouseEvent *)
{
if(isDragging) //如果鼠标松开了,那么还原鼠标按下标志位
{
isDragging = 0;
homing(); //使选中的数字回到屏幕中间
}
}
//void RollingBoxD::wheelEvent(QWheelEvent *e)
//{
// if(e->delta()>0)
// {
// m_deviation = (this->height() -1)/4;
// }
// else{
// m_deviation = -(this->height() -1)/4;
// }
// homing();
// repaint();
//}
//绘图事件
void RollingBoxD::paintEvent(QPaintEvent *)
{
QPainter painter(this); //创建画家类,指定绘图设备
painter.setRenderHint(QPainter::Antialiasing, true); //抗锯齿
int Width = width()-1;
int Height = height()-1;
if(m_deviation >= Height/4 && m_currentValue > m_minRange) //偏移量大于1/4的时候,数字减一
{
m_mouseSrcPos += Height/4; //鼠标起始位置重新设置,即加上1/4的高度
m_deviation -= Height/4; //偏移量重新设置,即减去1/4的高度
m_currentValue -= 1;
}
if(m_deviation <= -Height/4 && m_currentValue < m_maxRange) //同理,数字加一
{
m_mouseSrcPos -= Height/4;
m_deviation += Height/4;
m_currentValue += 1;
}
//中间数字
paintNum(painter,m_currentValue,m_deviation); //将选中数字画到中间
//两侧数字1
if(m_currentValue != m_minRange) //选中的数字不是最小,不是最大,那么就有两侧数字,然后画出两侧数字
paintNum(painter,m_currentValue-1,m_deviation-Height/4);
if(m_currentValue != m_maxRange)
paintNum(painter,m_currentValue+1,m_deviation+Height/4);
//两侧数字2,超出则不显示
if(m_deviation >= 0 && m_currentValue-2 >= m_minRange)
paintNum(painter,m_currentValue-2,m_deviation-Height/2);
if(m_deviation <= 0 && m_currentValue+2 <= m_maxRange)
paintNum(painter,m_currentValue+2,m_deviation+Height/2);
//中间数字两侧的边框
painter.setPen(QPen(QColor(70,144,249),2));
painter.drawLine(0,Height/8*3,Width,Height/8*3);
painter.drawLine(0,Height/8*5,Width,Height/8*5);
}
//画数字
void RollingBoxD::paintNum(QPainter &painter,int num,int deviation)
{
int Width = this->width()-1;
int Height = this->height()-1;
int size = (Height - qAbs(deviation))/m_numSize; //qAbs 返回输入参数对应类型的绝对值
int transparency = 255-510*qAbs(deviation)/Height; //设置透明度
int height = Height/2-3*qAbs(deviation)/5;
int y = Height/2+deviation-height/2;
QFont font;
font.setPixelSize(size); //设置像素大小
painter.setFont(font); //设置字体
painter.setPen(QColor(0,0,0,transparency)); //设置画笔
painter.drawText(QRectF(0,y,Width,height), //画文本,参数:QRectF参数:位置xy,长宽大小;对齐方式,居中对齐;内容
Qt::AlignCenter,
(QString::number(num)+tr("日")));
}
void RollingBoxD::homing()
{
//将数字矫正到中心
if(m_deviation > height()/8)
{
homingAni->setStartValue((height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValue--;
}
else if(m_deviation > -height()/8)
{
homingAni->setStartValue(m_deviation);
homingAni->setEndValue(0);
}
else if(m_deviation < -height()/8)
{
homingAni->setStartValue(-(height()-1)/8-m_deviation);
homingAni->setEndValue(0);
m_currentValue++;
}
emit currentValueChanged(m_currentValue); //发送当前数值改变信号
homingAni->start(); //开始动画
}
//获取鼠标移动偏移量
int RollingBoxD::readDeviation()
{
return m_deviation;
}
//设置偏移量
void RollingBoxD::setDeviation(int n)
{
m_deviation = n;
repaint();
}
最后就是把它们整合在一起了
整合控件
rollingbox.h
//时间滚动条控件(封装)
#ifndef ROLLINGBOX_H
#define ROLLINGBOX_H
#include <QTimer>
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <rollingboxy.h>
#include <rollingboxm.h>
#include <rollingboxd.h>
class RollingBox : public QWidget
{
Q_OBJECT
public:
explicit RollingBox(QWidget *parent = 0);
// int readValue(); //获取当前值
int readYear();
int readMonth();
int readDay();
int m_currYear;
int m_currMonth;
int m_currDay;
public slots:
void receiveValue();
private:
QTimer *time;
RollingBoxY *rby;
RollingBoxM *rbm;
RollingBoxD *rbd;
protected:
int m_maxRange; //设置偏移量
int maxValue();
};
#endif // ROLLINGBOX_H
rollingbox.cpp
#include <rollingbox.h>
RollingBox::RollingBox(QWidget *parent)
:QWidget(parent)
{
rby = new RollingBoxY(this);
rby -> move(60,0);
rby -> setFixedSize(200,300);
rbm = new RollingBoxM(this);
rbm -> move(260,0);
rbm -> setFixedSize(200,300);
rbd = new RollingBoxD(this);
rbd -> move(460,0);
rbd -> setFixedSize(200,300);
time = new QTimer(this);
time -> start(33); //每隔若干秒读取一次当前选中的值(default:30帧)
connect(time,SIGNAL(timeout()),this,SLOT(receiveValue()));
}
int RollingBox::maxValue()
{
//日期最大值(随年份和月份变化)
if(m_currMonth == 1 || m_currMonth == 3 || m_currMonth == 5 || m_currMonth == 7 || m_currMonth == 8
|| m_currMonth == 10 || m_currMonth == 12)
m_maxRange = 31;
else if(m_currMonth == 4 || m_currMonth == 6 || m_currMonth == 9 || m_currMonth == 11)
m_maxRange = 30;
else if(m_currMonth == 2 && ((m_currYear % 4 == 0 && m_currYear % 100 != 0) || m_currYear % 400 == 0))
m_maxRange = 29;
else m_maxRange = 28;
return m_maxRange;
}
void RollingBox::receiveValue()
{
m_currYear = rby -> readValue();
m_currMonth = rbm -> readValue();
m_currDay = rbd -> readValue();
rbd -> setRange(1,RollingBox::maxValue());
}
int RollingBox::readYear()
{
return m_currYear;
}
int RollingBox::readMonth()
{
return m_currMonth;
}
int RollingBox::readDay()
{
return m_currDay;
}
最后在想要添加滚动日期选择器的页面new一个RollingBox就行了。
参考资料
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献6条内容
所有评论(0)