QT触摸滑动效果,滚轮效果。
先看效果,鼠标滑动,触摸滑动,鼠标滚轮都可以。自动更改月的日数。
主要分析的是滚动的效果,上层调用怎么用都可以。
1. 整体程序结构
- 创建一个VerticalScroll的文件,形成一个类。这个类的父窗体必须是QWidget。
- 使用MainWindow中的一个QWidget,显示VerticalScroll的类。可以创建多个窗口。
- 类VerticalScroll,可以发送信号,也可以通过父窗体的程序改变各种设定。
2. VerticalScroll的代码,有详细注解的
- 使用方法:直接新建一个无界面文件,把 .h 和.cpp 复制进去就可以了。
- 滚动效果需要几个关键的变量
int Now_Value;//当前值
int Min_Value;//最小值
int Man_Value;//最大值
bool isDragging;//鼠标按下标志位
int Mouse_Press;//鼠标拖动值
int Deviation;//显示偏移量
- 先看 .h
#ifndef VERTICALSCROLL_H
#define VERTICALSCROLL_H
#include <QWidget> //Widget头文件
#include <QPainter> //画笔头文件
#include <QDebug> //打印头文件
#include <QMouseEvent> //鼠标头文件
#include <QWheelEvent> //滚轮头文件
class VerticalScroll : public QWidget
{
Q_OBJECT
public:
explicit VerticalScroll(QWidget *parent = nullptr);//指定父窗体必须是 QWidget
void SetRange(double min, double max);//设置范围
int ReadValue();//获取当前值
void SetValue(int value); //设定当前值
protected:
void mousePressEvent(QMouseEvent *Mouse); //按下
void mouseMoveEvent(QMouseEvent *Mouse); //移动
void mouseReleaseEvent(QMouseEvent *); //松开
void wheelEvent(QWheelEvent *event); //滚轮
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; //画图程序
void paintNum(QPainter &painter, double num, int deviation);//画图程序,调用的,写字程序
signals:
void CurrentValueChanged(int value);
private:
int Now_Value;//当前值
int Min_Value;//最小值
int Man_Value;//最大值
bool isDragging;//鼠标按下标志位
int Mouse_Press;//鼠标拖动值
int Deviation;//显示偏移量
};
#endif // VERTICALSCROLL_H
- 再看 .cpp
#include "verticalscroll.h"
VerticalScroll::VerticalScroll(QWidget *parent)
: QWidget(parent),
Now_Value(5),
Min_Value(0),
Man_Value(10),
isDragging(false),
Mouse_Press(0),
Deviation(0)
{
this->resize(150,230);//界面尺寸
}
void VerticalScroll::SetRange(double min, double max)//设置范围,父窗体调用
{
Min_Value = min;
Man_Value = max;
if(Now_Value < Min_Value)
Now_Value = Min_Value;
if(Now_Value > Man_Value)
Now_Value = Man_Value;
Deviation = 0;
update();
}
int VerticalScroll::ReadValue()//获取当前值,父窗体调用
{
return Now_Value;
}
void VerticalScroll::SetValue(int value)//设定当前值,父窗体调用
{
Now_Value = value;
Deviation = 0;
update();
}
void VerticalScroll::mousePressEvent(QMouseEvent *Mouse)//鼠标按下
{
isDragging = true;//记录鼠标按下标志位
Mouse_Press = Mouse->pos().y();//记录Y坐标,因为是上下滑动
}
void VerticalScroll::mouseMoveEvent(QMouseEvent *Mouse)//鼠标拖动
{
if (isDragging)//鼠标按下,的移动,才算拖动
{
Deviation = Mouse->pos().y() - Mouse_Press;//获取便宜量
int Height = height() - 1;//获取界面长
if (Deviation > (Height) / 3)
{
Deviation = (Height) / 3;
}
if (Deviation < -(Height) / 3)
{
Deviation = -(Height) / 3;
}
update();//更新显示
}
}
void VerticalScroll::mouseReleaseEvent(QMouseEvent *)//鼠标放开,弹回最近的数字
{
if (isDragging)
isDragging = false;
int Height = height() - 1;//获取界面长
if((Deviation > (Height/3)/2) && (Now_Value > Min_Value))
{
Now_Value -= 1;
}
if((Deviation < (-Height/3)/2) && (Now_Value < Man_Value))
{
Now_Value += 1;
}
Deviation = 0;//偏移归零
update();//更新显示
}
void VerticalScroll::wheelEvent(QWheelEvent *event)//滚轮
{
if(event->delta() > 0)//向上滚轮
{
if(Now_Value > Min_Value)
Now_Value -= 1;
}
else//向下滚轮
{
if(Now_Value < Man_Value)
Now_Value += 1;
}
Deviation = 0;
update();//更新显示
}
void VerticalScroll::paintEvent(QPaintEvent *)//绘制事件,调用update时更新显示
{
static int Old_Now_Value = 0;
QPainter painter(this);//创建画板
int Width = width() - 1;//获取长和宽
int Height = height() - 1;
painter.setRenderHints(QPainter::Antialiasing,true);//创建画板
painter.save();//保存当前绘制器状态
painter.setBrush(QColor(200,200,200));//画板颜色
painter.drawRect(0,0,width(),height());//画板尺寸
painter.restore();//恢复当前的绘制状态
//如果偏移了过大
if((Deviation >= Height/3) && (Now_Value > Min_Value))
{
Mouse_Press += Height/3;//偏移初值
Deviation -= Height/3;
Now_Value -= 1;
}
if((Deviation <= -Height/3) && (Now_Value < Man_Value))
{
Mouse_Press -= Height/3;//偏移初值
Deviation += Height/3;
Now_Value += 1;
}
paintNum(painter,Now_Value,Deviation);//显示当前值
if(Old_Now_Value != Now_Value)
{
Old_Now_Value = Now_Value;
emit CurrentValueChanged(Now_Value);
}
if(Now_Value > Min_Value)
paintNum(painter,Now_Value-1,Deviation-Height/3);//显示上一个值
if(Now_Value < Man_Value)
paintNum(painter,Now_Value+1,Deviation+Height/3);//显示下一个值
//补空位的一个显示,让过度平滑
if(Deviation > 0)//>0是-1,<0是+1
{
if(Now_Value > Min_Value+1)//显示-2的数字
paintNum(painter,Now_Value-2,-Height/3*2+Deviation);
}
else
{
if(Now_Value < Man_Value+1)//显示+2的数字
paintNum(painter,Now_Value+2,+Height/3*2+Deviation);
}
//画两个横杠,画面效果
QPen pen;//创建画笔
pen.setColor(QColor(40,40,40));//颜色
pen.setWidth(Height/40);//线宽
painter.setPen(pen);//拿起画笔
painter.drawLine(QPoint(15,Height/3),QPoint(Width-15,Height/3));//画两条线
painter.drawLine(QPoint(15,(Height/3)*2),QPoint(Width-15,(Height/3)*2));//画两条线
}
void VerticalScroll::paintNum(QPainter &painter, double num, int deviation)//画笔的指针,显示的数字,偏移量(+向下-向上)
{
int Width = width() - 1;//获取长和宽
int Height = height() - 1;
int size = (Height - qAbs(deviation)) / 12; //偏移量越大,数字越小
int transparency = 255 - 255 * qAbs(deviation) / Height;//偏移量越大,透明度越高
int height = Height / 3;
int y = Height / 2 + deviation - height / 2;
painter.setPen(QColor(0,0,0,transparency));//设置颜色和透明度
painter.setFont(QFont(painter.font().family(),static_cast<int>(size*1.5),750));//设置字体大小
painter.drawText(QRectF(0, y, Width, height),Qt::AlignCenter,QString::number(num)+"");//写字
}
- 简单说明一下,其实程序里都有注解。
主要功能是使用paintEvent绘制事件,调用update时更新显示
变量Deviation是偏移量,偏移量越大,字体越小,颜色越淡,就是效果
鼠标按下时候,记录一个Y值,移动改变Y值,随之改变偏移量。
鼠标放开时候,根据偏移量的大小,回弹的最近的数字上。
3.父窗体的调用
- 第一步:在 .h 里创建类指针。
VerticalScroll *My1_VerticalScroll;//创建类
VerticalScroll *My2_VerticalScroll;//创建类
VerticalScroll *My3_VerticalScroll;//创建类
- 显示窗口,调用函数
My1_VerticalScroll = new VerticalScroll(ui->widget);//new出一个VerticalScroll窗口
My1_VerticalScroll->move(0,0);//设置窗口位置
My1_VerticalScroll->SetRange(2010,2030);//设定最大最小值
My1_VerticalScroll->SetValue(2021);//设定当前值
- 连接槽
connect(My1_VerticalScroll,&VerticalScroll::CurrentValueChanged,[=](int value)
{
value = value;
int Days,Month,Year,NowDay;
Year = My1_VerticalScroll->ReadValue();//获取年
Month = My2_VerticalScroll->ReadValue();//获取月
NowDay= My3_VerticalScroll->ReadValue();//获取日
Days = GetDaysOfMonth(Year,Month);//获取天数
My3_VerticalScroll->SetRange(1,Days);//设定天数
DateTime.setDate(QDate(Year,Month,NowDay));//更新日期
qDebug()<<DateTime;
});
4.可以扩展的地方
- 这个程序是垂直滑动的,可以按这个思路改成水平滑动的
- 滚动的数字是int型,如果需要小数点,可以改成double,上下加减的数值也可以用变量。
- 界面尺寸大小,现在是固定的,可以安要求改变。
- 后续把工程源码上传,敬请期待!
- 工程链接