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

QT写的动态正弦曲线图显示并打印

创建一个显示正弦曲线的 QChartView,并通过定时器不断更新图表数据,模拟动态数据。此外,还包含了一个在特定时间自动将图表导出为 PDF 文件的功能。

代码分析和注释

#include <QApplication>
#include <QMainWindow>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QRandomGenerator>
#include <QTimer>
#include <QDebug>
#include <QFileDialog>
#include <QPrinter>
#include <QPainter>
#include <iomanip>
#include <sstream>
#include <ctime>

// 获取当前日期和时间格式化为字符串
std::string getCurrentDateTime() {
    auto now = std::time(nullptr); // 获取当前时间的时间戳
    std::tm* localTime = std::localtime(&now); // 将时间戳转换为本地时间

    std::ostringstream oss; // 创建字符串流对象
    oss << std::put_time(localTime, "%Y-%m-%d-%H-%M-%S"); // 格式化时间字符串为 "年-月-日-时-分-秒"
    return oss.str(); // 返回格式化后的字符串
}

QT_CHARTS_USE_NAMESPACE // 使用 Qt Charts 命名空间

int main(int argc, char *argv[])
{
    QApplication a(argc, argv); // 创建 QApplication 对象

    QMainWindow window; // 创建主窗口
    QChartView *chartView = new QChartView(&window); // 创建图表视图
    window.setCentralWidget(chartView); // 将图表视图设置为主窗口的中心部件

    QChart *chart = new QChart(); // 创建图表对象
    chart->setTitle(QString::fromStdWString(L"正弦运动曲线")); // 设置图表标题
    chart->legend()->hide(); // 隐藏图例

    chartView->setChart(chart); // 将图表设置到图表视图中
    chartView->setRenderHint(QPainter::Antialiasing, true); // 设置抗锯齿渲染

    QLineSeries *series = new QLineSeries(); // 创建线条系列对象
    chart->addSeries(series); // 将线条系列添加到图表中
    chart->createDefaultAxes(); // 创建默认的坐标轴

    int currentIndex = 0; // 当前数据点索引,用于计算滚动位置

    QValueAxis *axisX = qobject_cast<QValueAxis *>(chart->axes(Qt::Horizontal).at(0)); // 获取 X 轴
    axisX->setTickCount(20); // 设置 X 轴的刻度数
    axisX->applyNiceNumbers(); // 使 X 轴的刻度数看起来更友好
    axisX->setRange(0, 800); // 设置 X 轴的范围

    QValueAxis *axisY = qobject_cast<QValueAxis *>(chart->axes(Qt::Vertical).at(0)); // 获取 Y 轴
    axisY->setTickCount(9); // 设置 Y 轴的刻度数
    axisY->applyNiceNumbers(); // 使 Y 轴的刻度数看起来更友好
    axisY->setRange(0, 120); // 设置 Y 轴的范围

    // 初始化数据点
    qreal startX = 0;
    for (int i = 0; i < 800; ++i) {
        series->append(startX + i, 60. + 40. * sin(3.14159 * i / 180)); // 生成正弦数据点
    }

    QTimer timer; // 创建定时器
    timer.setInterval(50); // 设置定时器间隔为 50 毫秒
    QObject::connect(&timer, &QTimer::timeout, [&](){
        if (series->points().size() >= 800)
        {
            int n = series->points().size() - 800;
            series->removePoints(0, n); // 当数据点超过 800 时,移除多余的点
            currentIndex -= n;
            qDebug() << "remove " << n; // 打印移除的点数
        }

        qDebug() << currentIndex; // 打印当前数据点索引
        // 移动数据点并添加新的数据点
        series->append(series->points().last().x() + 1, 60. + 40. * sin((3.14159 * series->points().last().x() + 1) / 180));

        // 计算滚动后的横坐标范围
        qreal minX = series->points().at(currentIndex).x();
        qreal maxX = series->points().last().x();

        qreal targetMinX = minX + 1;
        qreal targetMaxX = maxX + 1;

        axisX->setRange(targetMinX, targetMaxX); // 更新 X 轴的范围
        currentIndex++;
    });

    timer.start(); // 启动定时器

    // 设置主窗口的背景颜色
    QPalette pal = window.palette();
    pal.setColor(QPalette::Window, QRgb(0x40434a));
    pal.setColor(QPalette::WindowText, QRgb(0xd6d6d6));
    window.setPalette(pal);

    // 设置图表的主题
    QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(QChart::ChartThemeBlueCerulean);
    chartView->chart()->setTheme(theme);

    // 设置主窗口的初始大小
    window.resize(1600, 900);
    window.show(); // 显示主窗口

    // 使用单次定时器在 2 秒后导出图表为 PDF 文件
    QTimer::singleShot(2000, [&]()
    {
        std::string str = getCurrentDateTime(); // 获取当前日期和时间字符串
        QString filePath = "chart-" + QString::fromStdString(str) + ".pdf"; // 生成 PDF 文件路径
        qDebug() << filePath; // 打印文件路径

        // 创建打印机对象
        QPrinter printer(QPrinter::HighResolution);
        printer.setOutputFormat(QPrinter::PdfFormat); // 设置输出格式为 PDF
        printer.setOutputFileName(filePath); // 设置输出文件名
        printer.setPageSize(QPrinter::A4); // 设置页面大小为 A4
        printer.setOrientation(QPrinter::Orientation::Landscape); // 设置页面方向为横向

        // 获取页面边缘的边距
        QPrinter::Margins margin = printer.margins();

        // 获取页面矩形(打印区域)
        QRectF pageRect = printer.pageRect(QPrinter::DevicePixel);

        // 获取图表的绘制区域
        QRectF chartRect = chart->plotArea();

        // 计算缩放比例
        qreal scaleX = (pageRect.width() - margin.left - margin.right) / chartRect.width();
        qreal scaleY = (pageRect.height() - margin.top - margin.bottom) / chartRect.height();
        qreal scale = qMin(scaleX, scaleY); // 选择较小的缩放比例以保持图表比例不变

        // 打印边距和页面矩形信息
        qDebug() << "margin:" << margin.top << "," << margin.bottom;
        qDebug() << "pageRect:" << pageRect;
        qDebug() << "pageRect Width:" << pageRect.width();
        qDebug() << "pageRect Height:" << pageRect.height();

        // 调整图表的绘制区域以适应页面大小
        chartRect.setWidth(chartRect.width() * scale);
        chartRect.setHeight(chartRect.height() * scale);

        // 打印调整后的图表矩形信息
        qDebug() << "chartRect:" << chartRect;
        qDebug() << "chartRect Height:" << chartRect.height();

        // 计算图表在页面上的居中位置
        qreal x = (pageRect.width() - chartRect.width()) / 2;
        qreal y = (pageRect.height() - chartRect.height()) / 2;

        // 打印图表居中位置信息
        qDebug() << x << "," << y;
        qDebug() << "chartRect:" << chartRect;

        // 创建画布并绘制图表
        QPainter painter;
        if (!painter.begin(&printer)) { // 开始绘制
            qWarning("Failed to start printer");
            return;
        }

        // 将图表绘制区域居中到页面上
        painter.translate(QPoint(x / 2, pageRect.top() + chartRect.top() + y / 2)); // 逻辑有点奇怪,但测试看上去是对的

        chartView->render(&painter); // 渲染图表到画布上
        painter.end(); // 结束绘制

        // 打印保存的 PDF 文件路径
        qDebug() << "PDF file saved to:" << filePath;
    });

    return a.exec(); // 运行应用程序
}

代码功能解析

  1. 获取当前日期和时间

    • getCurrentDateTime 函数使用 <ctime> 和 <iomanip> 头文件中的函数获取当前日期和时间,并格式化为 “年-月-日-时-分-秒” 的字符串。
  2. 创建主窗口和图表视图

    • QApplication 创建应用程序对象。
    • QMainWindow 创建主窗口。
    • QChartView 创建图表视图并设置为主窗口的中心部件。
  3. 创建和配置图表

    • QChart 创建图表对象并设置标题。
    • QLineSeries 创建线条系列对象并添加到图表中。
    • QValueAxis 创建和配置 X 轴和 Y 轴,包括刻度数、范围和自动友好的刻度数。
  4. 初始化数据点

    • 生成 800 个正弦数据点并添加到线条系列中。
  5. 定时器更新数据

    • QTimer 创建定时器并设置间隔为 50 毫秒。
    • 定时器每次触发时,检查数据点数量是否超过 800,如果超过则移除多余的点。
    • 添加新的数据点并更新 X 轴的范围。
    • 使用 currentIndex 记录当前的数据点索引,以便计算图表的滚动位置。
  6. 设置主窗口样式和图表主题

    • 设置主窗口的背景颜色和文本颜色。
    • 设置图表的主题为 ChartThemeBlueCerulean
  7. 导出图表到 PDF

    • 使用 QTimer::singleShot 在 2 秒后执行导出操作。
    • QPrinter 创建打印机对象并设置输出格式为 PDF,页面大小为 A4,方向为横向。
    • 计算页面的边距和打印区域。
    • 计算图表的缩放比例,使图表在页面上居中显示。
    • 使用 QPainter 创建画布并绘制图表到 PDF 文件中。
    • 保存 PDF 文件并打印路径信息。

注意事项

  • 缩放逻辑:计算缩放比例时,选择了较小的比例以保持图表的比例不变。
  • 居中位置painter.translate 用于将图表居中显示在页面上,逻辑可能需要根据实际需求进行调整。
  • 定时器:使用 QTimer 模拟动态数据的变化,间隔设置为 50 毫秒,可以根据实际需求调整间隔时间。

打印好的pdf文件显示


http://www.kler.cn/a/459296.html

相关文章:

  • 多模态机器人
  • 24.小R的随机播放顺序<字节青训营-中等题>
  • 实战指南:Shiro、CAS打造完美单点登录体验
  • 运行python程序报错 undefined symbol: ffi_type_uint32 的参考解决方法
  • 马原复习笔记
  • AWS K8s 部署架构
  • 在云服务器中编译IDF(ESP32库)
  • 2024年个人总结
  • 使用 PyInstaller 和 hdiutil 打包 Tkinter 应用为 macOS 可安装的 DMG 文件
  • 统计颜色Count Color(POJ2777)题解
  • 【UE5 C++课程系列笔记】16——DeveloperSettings(开发者设置)的基本使用——创建配置文件
  • 【linux进程】进程终止进程等待
  • CSS(层叠样式表)基础选择器,文字控制属性
  • SpringBoot发邮件(带附件)
  • 《Vue进阶教程》第二十九课:立即执行的回调
  • OpenTK 光照与材质详解
  • 瓷砖缺陷检测数据集,使用yolo,coco json,pasical voc xml格式标注,可识别边缘崩裂,破洞,裂缝等缺陷,一共7992张原始图
  • 批量新建日报表只需10秒-Excel易用宝
  • HarmonyOS初步探索
  • [羊城杯 2024]miaoro