Qt实践之用鼠标事件使QChart图表前移后移、时间坐标轴放大缩小

该文章描述了一个Qt应用中如何处理滚轮事件来实现图表曲线的前移后移和放大缩小。使用定时器事件实时更新以时间为坐标轴的图表,保持图表数据在最近30分钟内。滚轮控制时间轴范围,按下CTRL键则进行缩放,单独滚动则前后移动数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

头文件声明

protected:
    void wheelEvent(QWheelEvent *event) override;
private slots:
    void onTimeout();
private:
    void dragPressureChart(int delta);
    void zoomPressureChart(QWheelEvent *wheelEvent);
    void showStreamStatusChart();
    
	int m_totalDelta;  		//记录前移或后移的时间刻度
	QTimer *m_timer;

成员变量初始化

 m_totalDelta = 0;
 m_timer = new QTimer();
 QObject::connect(m_timer, &QTimer::timeout, this, &StatusPanel::onTimeout);
 m_timer->start(1000);

实现滚轮事件

void StatusPanel::wheelEvent(QWheelEvent *event)
{
    if (m_statusChartView->geometry().contains(m_statusChartView->mapFrom(this, event->position().toPoint())))
    {
        if (event->modifiers() & Qt::ControlModifier)
        {
            zoomPressureChart(event);	// CTRL加滚动,放大或缩小坐标轴的范围
        }
        else
        {
            dragPressureChart(event->angleDelta().y());		// 单独滚动,前移或后移图表曲线,当滚轮上滚时参数为120,反之为-120
        }
    }
    event->accept();	//来接受事件,表示事件已经被处理。如果不调用该函数,事件会继续传递给其他可能处理该事件的控件
}

实现前移后移图表曲线


void StatusPanel::dragPressureChart(int delta)
{
    if (delta > 0 && m_totalDelta < 1800) // 30 minutes, scroll up		// 允许前移或后移的范围为30分钟
    {
        m_axisX->setMin(m_axisX->min().addSecs(-60));
        m_axisX->setMax(m_axisX->max().addSecs(-60));
        m_totalDelta += 60;
    }
    else if (delta < 0 && m_totalDelta > -1800) // scroll down
    {
        m_axisX->setMin(m_axisX->min().addSecs(60));
        m_axisX->setMax(m_axisX->max().addSecs(60));
        m_totalDelta -= 60;
    }
}

实现放大缩小时间坐标轴


void StatusPanel::zoomPressureChart(QWheelEvent *wheelEvent)
{
    static int axisRange[3] = {3, 5, 10};		// 时间轴改变的幅度共三档,3*2, 5*2, 10*2
    static int wheelCount = 0;		// 记录滚轮有效滚动次数
    static int callCount = 0;		//记录函数调用次数,每调用三次,有效滚动次数加一,坐标轴改变一次

    callCount++;
    if (callCount >= 3)
    {
        wheelCount++;
        Count = 0;
        if (wheelCount < 0)
        {
            wheelCount = -wheelCount;
        }
        if (wheelCount > 2)
        {
            wheelCount = 0;
        }
        QDateTime min = QDateTime::currentDateTime().addSecs(-60 * axisRange[wheelCount]);
        QDateTime max = QDateTime::currentDateTime().addSecs(60 * axisRange[wheelCount]);
        m_axisX->setRange(min, max);
        m_totalDelta = 0;		// 清零,表示当前无前移或后移曲线
    }
}

实现定时器事件,实时更新以时间为坐标轴表示的图表

void MyClass::onTimeout()
{
	showStreamStatusChart();
}

定时器事件实际要做的是从界面获取数据源,并根据数据源实时更新图表曲线,每次使曲线前进一分钟


void MyClass::showStreamStatusChart()
{
	QLineSeries *dataSeries = dynamic_cast<QLineSeries *>(m_statusChart->series().at(streamIndex));
    m_axisX = qobject_cast<QDateTimeAxis *>(m_statusChart->axisX(dataSeries));
    QDateTime currentTimePoint = QDateTime::currentDateTime();

    if (currentTimePoint.secsTo(m_axisX->min()) < -3 * 60)
    {
        if (currentTimePoint.operator>=(m_axisX->min()) && currentTimePoint.operator<=(m_axisX->max()))
        {
            QDateTime newMax = m_axisX->max().addSecs(60);
            if (newMax <= currentTimePoint.addSecs(90))
            {
                m_axisX->setMin(m_axisX->min().addSecs(60));
                m_axisX->setMax(newMax);
            }
        }
        else if (currentTimePoint.secsTo(m_axisX->min()) < -31 * 60)		//	使图表只保留前后30分钟的数据
        {
            m_axisX->setMin(m_axisX->min().addSecs(60));
            m_axisX->setMax(m_axisX->max().addSecs(60));
        }
    }
        double currentPressure =  m_ui->labelPump1Pressure->text().toDouble(); 		// 从界面获取图表曲线的数据源
        dataSeries->append(QDateTime::currentMSecsSinceEpoch(), currentPressure);
    	dataSeries->show();
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值