当前位置: 首页 > news >正文

上位机使用QtCharts绘图

工程配置

CMake文件

find_package(Qt5 COMPONENTS Charts REQUIRED)

target_link_libraries(zhd-desktop PRIVATE Qt5::Charts)

包含头文件以及名称空间(这个很重要,没有包含名称空间编译器会提示找不到相关的类型)

#include <QtCharts>

using namespace QtCharts;

初始化

初始化Chart

// 创建图表
QChart *chart = new QChart();
chart->setTitle("Valve Data");

// 隐藏图例
chart->legend()->setVisible(false);

// 创建图表视图
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);

QHBoxLayout *hLayout = new QHBoxLayout(ui->view);
hLayout->addWidget(chartView);
hLayout->setContentsMargins(0, 0, 0, 0);

波形

每一道波形就是一个QLineSeries,每个QLineSeries都要和X轴和Y轴进行绑定

m_temperature = new QLineSeries();
m_temperature->setColor(Qt::red);
m_temperature->setPointsVisible(true);

m_pressure = new QLineSeries();
m_pressure->setColor(Qt::blue);
m_pressure->setPointsVisible(true);

m_position = new QLineSeries();
m_position->setColor(Qt::black);
m_position->setPointsVisible(true);

m_pressureSetpt = new QLineSeries();
m_pressureSetpt->setColor(Qt::darkYellow);
m_pressureSetpt->setPointsVisible(true);

为了使波形更有区分度,需要配置不同的颜色,建议跟Y轴刻度的颜色保持一致,特别是轴比较多的情况下

void setAxisColor(QAbstractAxis *axis, const QColor &color)
{
    axis->setGridLineColor(color);
    axis->setLinePenColor(color);
    axis->setLabelsColor(color);
    axis->setTitleBrush(color);
}

X轴

X轴一般是时间轴,时分秒格式:hh:mm:ss

QDateTimeAxis *timeAxis = new QDateTimeAxis();
timeAxis->setTitleText("Time");
timeAxis->setFormat("hh:mm:ss");
chart->addAxis(timeAxis, Qt::AlignBottom);
series1->attachAxis(timeAxis);
series2->attachAxis(timeAxis);

Y轴

Y轴:左侧和右侧都可以添加刻度尺

// 左侧刻度尺
QValueAxis *pressureSetpt = new QValueAxis();
pressureSetpt->setTitleText("Pressure Setpt (Torr)");
pressureSetpt->setRange(0, 25);
chart->addAxis(pressureSetpt, Qt::AlignLeft);
series1->attachAxis(pressureSetpt);

QValueAxis *pressure = new QValueAxis();
pressure->setTitleText("Pressure (Torr)");
pressure->setRange(0, 25);
chart->addAxis(pressure, Qt::AlignLeft);
series1->attachAxis(pressure);

// 右侧刻度尺
QValueAxis *driverTemperature = new QValueAxis();
driverTemperature->setTitleText("Driver temperature");
driverTemperature->setRange(0, 100);
chart->addAxis(driverTemperature, Qt::AlignRight);
series2->attachAxis(driverTemperature);

QValueAxis *positionAxis = new QValueAxis();
positionAxis->setTitleText("Position (%)");
positionAxis->setRange(0, 100);
chart->addAxis(positionAxis, Qt::AlignRight);
series2->attachAxis(positionAxis);

绘图

实时绘制波形点:往QLineSeries里边添加数据,用append接口

QDateTime currentTime = QDateTime::currentDateTime();
if(m_resumePause) {
    m_timeAxis->setRange(currentTime.addSecs(-10), currentTime);
}

if(m_channels[0]) {
    m_pressure->append(currentTime.toMSecsSinceEpoch(), pressure);
    if (m_pressure->count() > m_max) {
        m_pressure->remove(0);
    }
}

if(m_channels[1]) {
    m_position->append(currentTime.toMSecsSinceEpoch(), position);
    if (m_position->count() > m_max) {
        m_position->remove(0);
    }
}

if(m_channels[2]) {
    m_pressureSetpt->append(currentTime.toMSecsSinceEpoch(), pressureSetpt);
    if (m_pressureSetpt->count() > m_max) {
        m_pressureSetpt->remove(0);
    }
}

if(m_channels[3]) {
    m_temperature->append(currentTime.toMSecsSinceEpoch(), valveTemperature);
    if (m_temperature->count() > m_max) {
        m_temperature->remove(0);
    }
}

注意事项

1.时间轴要实时移动到正确的时间窗口范围

2.QLineSeries波形点之后到达一定的数据量需要删除一些点以确保buffer不会写爆(频繁申请内存导致卡顿)

进阶

QtCharts自带的时间轴比较丑陋,如果想要定制的话,可以参考以下方法进行样式修改

  1. 自定义QValueAxis作为X轴
  2. 捕获QValueAxis::rangeChanged信号,获取QChartView里边的scene,同时也可以获取到刻度的左右边界minmax
  3. 删除scene(QGraphicsScene)里边的所有items,即原有的刻度不要了
  4. QGraphicsScene即基础上画刻度,每一个刻度就是一个QGraphicsLineItem

代码参考

// 动态修改 X 轴标签为时间格式,并绘制刻度线
QObject::connect(axisX, &QValueAxis::rangeChanged, [axisX, chartView](qreal min, qreal max) {
    QGraphicsScene *scene = chartView->scene();

    // 检查 min 和 max 是否有效
    if (qIsNaN(min) || qIsNaN(max) || qIsInf(min) || qIsInf(max)) {
    	// qWarning() << "Invalid min or max value:" << min << max;
    	return;
    }

    // 检查 plotArea 是否有效
    if (chartView->chart()->plotArea().width() <= 0 || chartView->chart()->plotArea().height() <= 0) {
    	//  qWarning() << "Invalid plot area size";
    	return;
    }

    // 清除旧的标签和刻度线
    for (QGraphicsItem *item : scene->items()) {
        if (item->data(0).toString() == "custom_label" || item->data(0).toString() == "custom_line") 		{
            scene->removeItem(item);
            delete item;
        }
    }

    // 生成 10 个刻度
    int tickCount = 10;  // 总共 10 个刻度
    qreal tickInterval = (max - min) / (tickCount - 1);  // 计算刻度间隔

    for (int i = 0; i < tickCount; ++i) {
        qreal value = min + i * tickInterval;

        // 检查 value 是否有效
        if (qIsNaN(value) || qIsInf(value)) {
            // qWarning() << "Invalid value:" << value;
            continue;
        }

        QDateTime dateTime = QDateTime::fromSecsSinceEpoch(value);

        // 计算刻度线的位置
        qreal x = chartView->chart()->plotArea().left() +
        (value - min) / (max - min) * chartView->chart()->plotArea().width();

        // 检查 x 是否有效
        if (qIsNaN(x) || qIsInf(x)) {
            // qWarning() << "Invalid x coordinate:" << x;
            continue;
        }

        // 只在偶数刻度绘制时间标签和黑线
        if (i % 2 == 0) {
            // 绘制时间标签
            QString label = dateTime.toString("hh:mm:ss");
            QGraphicsTextItem *textItem = scene->addText(label);
            qreal textWidth = textItem->boundingRect().width();  // 获取标签宽度
            qreal textHeight = textItem->boundingRect().height();  // 获取标签高度

            // 调整标签位置,使其居中对齐刻度线
            textItem->setPos(x - textWidth / 2, chartView->chart()->plotArea().bottom() + 10);
            textItem->setData(0, "custom_label");  // 标记为自定义标签

            // 绘制黑线
            qreal lineLength = 10;  // 刻度线长度
            QGraphicsLineItem *lineItem = scene->addLine(x, chartView->chart()->plotArea().bottom(),
            x, chartView->chart()->plotArea().bottom() + lineLength,
            QPen(Qt::black));
            lineItem->setData(0, "custom_line");  // 标记为自定义刻度线
        }
    }
});

打包

软件打包,需要添加Qt5Charts这个dll

Qt5Charts.dll

版权

版权问题,商用的话可能会被Qt请喝茶
在这里插入图片描述

相关文章:

  • linux 命令 tail
  • numpy.random 用法
  • 软文推广发布渠道有哪些适合作为首发平台?首发平台有哪些好处?
  • 200多种算法应用于二维和三维无线传感器网络(WSN)覆盖场景
  • Tomcat Session 反序列化漏洞(CVE-2025-24813)
  • ubuntu24.04执行nvidia-smi报错,实际生产报错,处理过程
  • Mybatis 框架学习
  • Android Composable 与 View 的联系和区别
  • 【xv6操作系统】页表与写时拷贝解析及相关实验设计
  • 简单说一说ADSP-BF537的开发
  • 前端无限滚动内容自动回收技术详解:原理、实现与优化
  • 健康医疗:动态代理 IP 保障医疗数据安全,提升远程医疗服务质量!
  • lua C语言api学习2 在C语言中使用lua语言
  • 【eNSP实战】三层交换机使用ACL实现网络安全
  • 多功能网络工具,解锁网络深度分析与便捷管理
  • Qt项目中集成第三方模块的.pri文件
  • 【Linux 内核 | 操作系统 | 内核编译】内核编译中与锁调试相关的设置有哪一些?内核 Debug 选项中 LockDep 和其他锁调试选项详解
  • QT基础十四、绘图
  • 微信开发者工具内建终端使用不了npm,但是cmd可以
  • 在windows10系统上安装docker,然后在容器中运行GPU版本的Pytorch,并使用vscode连接该容器
  • 钱进已任外交部新闻司副司长
  • 人民日报:不能层层加码,要层层负责
  • 国家外汇管理局:4月货物贸易项下跨境资金净流入649亿美元
  • 北美票房|华纳又赢了,《死神来了6》开画远超预期
  • 国家主席习近平任免驻外大使
  • 历史缝隙里的人︱觑功名如画饼:盛世“做题家”的攀爬与坠落