创建一个显示正弦曲线的 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(); // 运行应用程序
}
代码功能解析
-
获取当前日期和时间:
getCurrentDateTime
函数使用<ctime>
和<iomanip>
头文件中的函数获取当前日期和时间,并格式化为 “年-月-日-时-分-秒” 的字符串。
-
创建主窗口和图表视图:
QApplication
创建应用程序对象。QMainWindow
创建主窗口。QChartView
创建图表视图并设置为主窗口的中心部件。
-
创建和配置图表:
QChart
创建图表对象并设置标题。QLineSeries
创建线条系列对象并添加到图表中。QValueAxis
创建和配置 X 轴和 Y 轴,包括刻度数、范围和自动友好的刻度数。
-
初始化数据点:
- 生成 800 个正弦数据点并添加到线条系列中。
-
定时器更新数据:
QTimer
创建定时器并设置间隔为 50 毫秒。- 定时器每次触发时,检查数据点数量是否超过 800,如果超过则移除多余的点。
- 添加新的数据点并更新 X 轴的范围。
- 使用
currentIndex
记录当前的数据点索引,以便计算图表的滚动位置。
-
设置主窗口样式和图表主题:
- 设置主窗口的背景颜色和文本颜色。
- 设置图表的主题为
ChartThemeBlueCerulean
。
-
导出图表到 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