首页 > 其他分享 >QT写的动态正弦曲线图显示并打印

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

时间:2024-12-29 21:01:50浏览次数:3  
标签:并打印 定时器 QT 正弦曲线 series 图表 设置 创建 include

创建一个显示正弦曲线的 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文件显示

标签:并打印,定时器,QT,正弦曲线,series,图表,设置,创建,include
From: https://blog.csdn.net/joshua0137/article/details/144778201

相关文章

  • Windows10 64环境下用Qt5.12.12自带的mingw730_64构建编译OpenCV4.1.0时cmake-3.20.6
    一、环境条件说明:操作系统:Windows1064环境编译工具:用Qt5.12.12自带的mingw730_64构建构建对象:编译OpenCV4.1.0的Release64位和Debug64位动态链接库构建工具:CMake中的参数配置二、cmake-3.20.6中的参数配置1、按照下图配置好OpenCV4.1.0的源代码目录和构建编译输出目录,然......
  • Qt笔记:文件I/O操作
    一、铺垫1.Qt中的所有类都是已经封装好的;拿出来直接用就可以;只不过是种类太过于繁多,以及继承的太杂;所以对与我这样的初学者来说眼花缭乱;2.但是不可否认;Qt是相当能打的,因为他从90年代打到了现在,在没有被淘汰的同时,还被太多的公司使用;牛到了一定的程度。3.Qt框架的开发比C++98......
  • Ubuntu20.04安装Qt5.15.2并配置qml_ros_plugin插件
    安装QtQt老版本采用离线安装,新版本采用在线安装器安装,在官网安装速度很慢,一般在国内的源下载。在中科大源下载Qt在线安装器http://mirrors.ustc.edu.cn/qtproject/official_releases/online_installers/安装依赖sudoaptinstallgccg++makecmakebuild-essentiallibgl1-......
  • 基于Qt的qss登录界面优化
    目标在登录界面的登录取消按钮进行以下设置:使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数。将登录按钮使用qt5版本的连接到自定义的槽函数中,在槽函数中判断ui界面上输入的账号是否为"admin",密码是否为"123456",如果......
  • [开源]用QT+OPENCV做了一个图片处理软件
    yusongmin1/QT_OPENCV界面如下基本功能,基本上没有基于opencv的库函数,手搓关于常见的传统图片处理的算法的开发,包括了内置图片,图片加载与保存,图片变换GRB2GRAY,RGB2HSV镜像,水平镜像,垂直镜像,负90度到正90度之间的旋转,阈值分割,反向腐蚀膨胀,开运算闭运算直方图......
  • systemd服务(二):Qt程序做自启动时,不能正常运行
    *: systemd服务中文手册:https://www.jinbuguo.com/systemd/systemd.exec.html 背景:不管是,直接运行qt程序,还是使用sh脚本来运行qt程序,都是正常的但是加入到systemd自启动服务后,总是启动不了Qt程序,通过sudoststemctlstatustesthuqt和  journalctl-utesthuqt查询日......
  • Qt天气预报系统设计界面布局第一部分
    Qt天气预报系统1、界面布局第一部分1.1改变窗口背景色1.2添加第一部分1.3修改控件名称1、界面布局第一部分1.1改变窗口背景色先给窗口换个背景色,把鼠标放到界面上,单击鼠标右键,选择改变样式表点击添加颜色旁边的黑色倒三角,然后选择background-color改变背景色,也......
  • Qt 软件调试——windbg初篇(一)
    https://blog.csdn.net/weixin_39568531/article/details/134787829 在上一篇《Qt软件调试(二)使用dump捕获崩溃信息》中我们结尾处提示大家先准备好windbg,windbg是非常强大的调试工具,对于我们进行代码调试和分析异常有着非常重要的意义。在Qt软件调试这个系列的首篇,我们介绍了......
  • Qt 模型Model/视图View/代理Delegate
    一、模型/视图/代理架构简介1、应用程序中往往要存储大量的数据,并对它们进行处理,然后可以通过各种形式显示给用户,用户需要时还可以对数据进行编辑。2、Qt中的模型/视图架构就是用来实现大量数据的存储、处理及其显示的。3、MVC设计模式:(1)、模型(Model)是应用对象,用......
  • qt学习之增加checkBox
    在实际的开发过程中,有时会需要将单元格是控件居中的情况存在,发现加了布局之后,tablewidget的信号cellChanged无法响应,于是想了一个办法当checkBox的状态发生变化时,手动发送tablewidget改变的信号以下是两种在单元格中增加复选框的方法//第一种,setItem直接添加此处没有布局......