在这个项目中,创建了六种常见的图表,通过随机数据函数产生表中显示的数据,可以设置主题、动画效果、是否显示图注等功能
一、创建ui文件
主要就是提供一行选项栏,还有就是添加布局
二、代码
1.头文件
这个代码很简洁,定义了产生随机数据的函数,三个comboBox的初始化函数,以及六个图表的创建函数
QT_BEGIN_NAMESPACE
class QComboBox;
class QCheckBox;
class Ui_chartExample;
QT_END_NAMESPACE
QT_CHARTS_BEGIN_NAMESPACE
class QChartView;
class QChart;
QT_CHARTS_END_NAMESPACE
typedef QPair<QPointF,QString> Data;//注意一下这个数据类型
typedef QList<Data> DataList;
typedef QList<DataList> DataTable;
QT_CHARTS_USE_NAMESPACE
class ChartWidget:public QWidget
{
Q_OBJECT
public:
explicit ChartWidget(QWidget*parent=0);
~ChartWidget();
private Q_SLOTS:
void updateUI();
private:
DataTable generateRandomData(int listCount,int valueMax,int valueCount) const;
void populateTheemeBox();
void populateAnimatiopnBox();
void populateLegendBox();
void connectSignals();
QChart*createAreaChart()const;
QChart*createPieChart()const;
QChart*createBarChart(int valueCount)const;
QChart*createLineChart()const;
QChart*createSplineChart()const;
QChart*createScatterChart()const;
private:
int m_listCount;
int m_valueMax;
int m_valueCount;
QList<QChartView *> m_charts;
DataTable m_dataTable;
Ui_Form *m_ui;
};
需要注意的地方是关于qt命名空间的作用:
QT_BEGIN_NAMESPACE QT_END_NAMESPACE这两个宏用于开启和结束一个 Qt 命名空间(namespace)
class XXX;这些是前向声明(forward declaration),用于声明将在命名空间内定义的类。
前向声明允许在当前命名空间中声明这些类,而实际的类定义可以在稍后的代码中进行,从而帮助解决头文件之间的循环依赖问题。这么写的作用是将不同的类放在不同的命名空间中,以确保类名不会发生冲突,同时也能更好地组织代码。
例如,QComboBox、QCheckBox 和 Ui_chartExample 类都被放置在全局命名空间中,而 QChartView、QChart 类被放置在 QT_CHARTS 子命名空间中。这有助于维护代码的可读性和可维护性,并避免了可能的类名冲突问题。
qpair和qmap的区别
QPair和 QMap 是 Qt 框架中两种不同的数据结构,用于不同的目的。
1. QPair:
QPair 是用于存储两个值的数据结构。它简单地将两个值(可以是不同类型)组合成一个对,并且可以方便地访问这两个值。QPair`主要用于需要在一个对象中存储两个相关联的值,例如键值对、坐标等。例如:
QPair<int, QString> pair(42, "Hello");
int value = pair.first; // 获取第一个值
QString text = pair.second; // 获取第二个值
2. QMap:
QMap 是一种关联容器,用于存储键值对。它类似于 C++ 标准库中的 std::map。QMap 允许您将一个键与一个值关联起来,并且可以通过键来查找对应的值。QMap 可以用于实现字典、映射等功能。例如:
QMap<QString, int> map;
map.insert("apple", 5);
map.insert("banana", 3);
int appleCount = map["apple"]; // 获取键为 "apple" 的值
总结:
QPair`用于存储两个相关的值,并且没有特定的键。
QMap 用于存储键值对,通过键来查找对应的值。
2.实现
创建图标的操作过程类似,我们只分析其中一种
// 创建面积图(山形图)
QChart *ChartWidget::createAreaChart() const
{
QChart *chart = new QChart();
chart->setTitle("Area chart");
QLineSeries *lowerSeries = 0;
QString name("Series ");
int nameIndex = 0;
// 第一层循环,遍历table中所有的list
for (int i(0); i < m_dataTable.count(); i++)
{
// 创建QLineSeries作为面积图的下边界(用折线表示)
QLineSeries *upperSeries = new QLineSeries(chart);
// 遍历datalist中的值
for (int j(0); j < m_dataTable[i].count(); j++)
{
Data data = m_dataTable[i].at(j);
if (lowerSeries)
{ // 获取上一次循环中创建的lowerSeries的所有坐标
const QVector<QPointF> &points = lowerSeries->pointsVector();
// 有疑问
upperSeries->append(QPointF(j, points[i].y() + data.first.y()));
}
// 第一次创建
else
{
upperSeries->append(QPointF(j, data.first.y()));
}
}
// 创建面积图
QAreaSeries *area = new QAreaSeries(upperSeries, lowerSeries);
area->setName(name + QString::number(nameIndex));
nameIndex++;
chart->addSeries(area);
// 用上一次循环的上边界作为这次循环的下边界 用来做出 累加的效果
lowerSeries = upperSeries;
}
// 创建坐标轴
chart->createDefaultAxes();
// 确定坐标轴x y的范围
chart->axes(Qt::Horizontal).first()->setRange(0, m_valueCount - 1);
chart->axes(Qt::Vertical).first()->setRange(0, m_valueMax);
QValueAxis *axisY = qobject_cast<QValueAxis *>(chart->axes(Qt::Vertical).first());
Q_ASSERT(axisY);
axisY->setLabelFormat("%1.f ");
return chart;
}
大致过程就是,创建一个图表类对象,将数据插入到对象中,最后创建坐标轴
这个面积图跟别的图还有些区别,它有上下边界
在上述代码中,使用上一个循环迭代中创建的上边界作为下一个循环迭代中的下边界是为了构建面积图的效果。面积图通常表示数据的累积或叠加情况,上下边界之间的区域被填充颜色以显示数据的范围。
具体来说,通过将上一个循环迭代中的上边界作为下一个循环迭代中的下边界,可以实现以下效果:
1. 数据累积:每次循环迭代中,上边界的数据会逐渐叠加。这意味着,当前迭代的上边界数据将在上一个迭代的上边界数据的基础上进行累加。这样,你就能够绘制出累积的面积图,反映了数据在时间或其他变量上的逐步叠加情况。
2. 区域填充:通过将上下边界传递给 `QAreaSeries`,面积图将根据这两个边界的数据点来填充区域。上边界和下边界之间的区域将以填充颜色显示,从而呈现出数据范围的覆盖情况。
总的来说,使用上一个循环迭代中的上边界作为下一个循环迭代中的下边界,可以实现面积图所需的数据累积和区域填充效果,从而更准确地反映数据的变化趋势和范围。这种设计使得绘制面积图变得更加方便和直观。
QChartView *chartView;
chartView = new QChartView(createAreaChart());
m_ui->gridLayout->addWidget(chartView, 1, 0);
m_charts << chartView;
qchartview类型为什么可以用addwidget()函数添加:
在Qt中,使用addWidget()
函数可以向布局中添加各种小部件(QWidget)。虽然QChartView
本身是QGraphicsView
的子类,而不是QWidget的子类,但它仍然可以在QWidget的布局中使用,因为Qt提供了适配和兼容机制,QChartView
内部会包含一个QGraphicsView
实例,用于显示图表内容。这使得你可以将QChartView
作为一个普通的QWidget来处理,将其添加到布局中,就像添加其他QWidget一样。
QPalette
QPalette
是 Qt 框架中用于管理窗口和小部件(Widget)颜色和外观属性的类。它提供了一种方式来定义和管理不同状态下的颜色、背景、前景等视觉元素,以及小部件在不同状态下的外观。
通过设置 QPalette
,你可以控制应用程序中各种小部件的外观,例如窗口的背景颜色、文本颜色、按钮的背景颜色、边框颜色等。QPalette
可以用于定制和修改应用程序的外观,使其与设计风格或用户喜好相符。
Q_ASSERT
Q_ASSERT
是 Qt 框架中用于断言的宏,用于在代码中进行运行时的条件检查。它在调试阶段起到了一种自我检查的作用,帮助开发人员在代码中检测逻辑错误或不合理的情况。
当使用 Q_ASSERT
宏时,如果断言条件为假(即条件不满足),则会触发断言失败,程序会在断言失败的位置停止执行并抛出一个断言异常。这有助于开发人员在开发和调试过程中快速发现和定位问题,以便进行修复
int x = 10;
Q_ASSERT(x > 0); // 如果 x 不大于 0,程序会停止执行并报告断言失败
代码下载链接