(QT-UI)十、实现时间轴缩放效果

  本系列预计实现

①刻度上方文字显示,

②时间轴拖动效果,

③时间轴刻度缩放,

④时间轴和其他控件联动显示,

⑤鼠标放置到时间轴,显示具体时间。

⑥通过定时器,实时更新时间轴

⑦时间轴上绘制时间片

完整代码可见GitHub - 754816/QT_TimeLine: qt时间轴实现效果

1、基础思路

设置不同的时间间隔模式,然后通过按钮,或者鼠标滚轮事件来切换间隔模式,完成时间轴缩放

鼠标滚轮滑动后,时间间隔缩小,切换为了半个小时

2、将时间划分6个间隔模式

这里给出常用的1分/5分/10分/30分/1小时/2小时,共6个档次,后续也可以按照情况自定义添加

enum TimeInterval
{
    _OneMin = 60,             //间隔1分钟
    _FiveMin = 300,           //间隔5分钟
    _TenMin = 600,            //间隔10分钟
    _ThirtyMin = 1800,        //间隔30分钟
    _OneHour = 3600,          //间隔1小时
    _TwoHour = 7200           //间隔2小时
};

定义时可以统一定义为秒,方便后续换算

3、缩放前后时间换算

在前两节中已经讲过了1小时间隔下,时间文字信息的计算,这里接着以1小时间隔切换到30分钟间隔为例,正中间红线的时间假设是12:34:56,原有的右边竖线的时间是12:00:00,切换后,应该是12:30:00,左边竖线的时间是13:00:00,切换后则依然是,12:34:56在12:30:00到13:00:00这个半小时间隔中。

切换后,那么带入到时间轴偏移中则是,时间轴相当于向左移动了4分56秒的距离

换算成比例则是(4*60+56)/   1800,约0.164的块间隔

假设一个块的长度为m_blockWidth,那么时间轴上的竖线,则是整体相当于左移动0.164*m_blockWidth

4、计算时间文字信息

和前两节思路一样,先根据中间红线对应的时间,将其处理为整点时间,12:34:56出,计算出最左边竖线展示的时间,然后按照时间间隔依次增加计算,12:34:56对应的最左侧时间文字,是10:00:00,最右侧时间文字是15:30:00。

同理,拓展1分/5分/10分/30分时计算如下

QString MyTimeLine::CalText(const int index, const QDateTime midDateTime, const int moveRatio)
{
    QTime time(0,0,0);
    //STEP 1: 将时间按照间隔进行取模处理,例如间隔为1h,12:34:56处理后为12:00:00, 间隔30分钟,处理后12:30:00
    QDateTime IntegerTime = midDateTime;

    if(_OneHour == m_IntervalType)
    {
        IntegerTime.setTime(QTime(midDateTime.time().hour(), 0, 0));
    }
    if(_TwoHour == m_IntervalType)
    {            //提醒:这里是做了按2舍去归整计算,不可以省略
        int hh = midDateTime.time().hour() / 2 * 2;
        IntegerTime.setTime(QTime(hh, 0, 0));
    }
    if(_OneMin == m_IntervalType)
    {
        IntegerTime.setTime(QTime(midDateTime.time().hour(), midDateTime.time().minute(), 0));
    }
    if(_FiveMin == m_IntervalType)
    {
        int mm = midDateTime.time().minute() / 5 * 5;
        IntegerTime.setTime(QTime(midDateTime.time().hour(), mm, 0));
    }
    if(_TenMin == m_IntervalType)
    {
        int mm = midDateTime.time().minute() / 10 * 10;
        IntegerTime.setTime(QTime(midDateTime.time().hour(), mm, 0));
    }
    if(_ThirtyMin == m_IntervalType)
    {
        int mm = midDateTime.time().minute() / 30 * 30;
        IntegerTime.setTime(QTime(midDateTime.time().hour(), mm, 0));
    }

    //STEP 2: 根据中间的时间和Interval,计算出最左边的时间
    QDateTime LeftTime = DateTimeUtil::sub(IntegerTime, (TimeLineStyle::TimeCount / 2) * m_IntervalType);

    //STEP 3: 根据偏移量,更新最左边的时间
    QDateTime MoveLeftTime = DateTimeUtil::sub(LeftTime, -1 * moveRatio * m_IntervalType);

    //STEP 4: 根据index,计算i个间隔后的时间
    time = DateTimeUtil::sub(MoveLeftTime, -1 * index * m_IntervalType).time();
    return time.toString("hh:mm:ss");
}

5、添加按钮事件和鼠标滚轮事件

点击其他地方的放大按钮,实际是执行了一次设置时间间隔,然后在MyTimeLine内部中,调用update函数,重新绘制图像

//STEP 1:在类外添加上放大和缩小按钮的槽函数响应 
   connect(ui->pushButton_ZoomIn, &QPushButton::clicked, this, [=](){
        ui->widget->SetTimeInterval(false);
    });
    connect(ui->pushButton_ZoomOut, &QPushButton::clicked, this, [=](){
        ui->widget->SetTimeInterval(true);
    });

//STEP 2:切换时间间隔,然后重新绘制
void MyTimeLine::SetTimeInterval(bool badd)
{
    QList<TimeInterval> list = {_OneMin, _FiveMin, _TenMin, _ThirtyMin, _OneHour, _TwoHour};
    int index = list.indexOf(m_IntervalType);
    if(0 < index && index < list.size() - 1)
    {
        if(badd) index++;
        else index--;
    }
    else if(0 == index && badd)
    {   //放大坐标轴
        index++;
    }
    else if(index == list.size() - 1 && !badd)
    {   //缩小坐标轴
        index--;
    }
    m_IntervalType = list.at(index);
    SetDateTime(m_MoveDateTime);
    //触发paintEvent进行绘制
    update();
}

//STEP 3:添加上鼠标滚轮事件,滚动后调用设置间隔的函数
void MyTimeLine::wheelEvent(QWheelEvent *event)
{
    if(event->delta() > 0)
    {
        SetTimeInterval(false);
    }
    else
    {
        SetTimeInterval(true);
    }
    m_label->setHidden(true);
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值