QtCharts
QtCharts是 Qt 框架的一个模块,用于创建和处理数据可视化图表。它提供了多种类型的图表和可视化工具,允许开发者在基于 Qt 的应用程序中轻松地展示数据。
图表类型:
- 折线图 (Line Chart):展示连续数据点之间的关系,适用于趋势和时间序列分析。
- 柱状图 (Bar Chart):展示类别数据的分布,适合比较不同类别的数据值。
- 饼图 (Pie Chart):展示部分与整体的关系,适合展示比例和百分比。
- 散点图 (Scatter Chart):展示数据点的分布,适合分析数据集中的相关性。
- 区域图 (Area Chart):类似于折线图,但区域图强调数据的累积变化。
- 盒状图 (Box-and-Whisker Chart):展示数据的分布和变异性,常用于统计分析。
.pro文件中添加:QT += charts
头文件 #include <QtCharts>
饼图绘:
在ui界面上添加QChartView 命名为:pie_1
void MainWindow::show_pie_1()
{
QList<QString>id;
//饼状图
QPieSeries pie_series1 = new QPieSeries(this);
pie_series1->clear();
pie_series1->setPieSize(0.8); //设置饼图占矩形区的大小,1为最大值
connect(pie_series1, SIGNAL(clicked(QPieSlice*)), this, SLOT(onPieSeriesClicked(QPieSlice*)));//饼图动画
QList<qreal> list_data;
QList<QString> list_name;
//定义各扇形切片的颜色
// static const QStringList list_pie_color = {"#6480D6","#A1DC85","#FFAD25","#FF7777","#84D1EF","#4CB383",""};
//遍历数据库-获取数据
QSqlQuery q_select(db);
q_select.prepare("SELECT * FROM slice_v2 WHERE TRIM(status)='11'");
q_select.setForwardOnly(true);
q_select.exec(); //运行数据库
int i_max = q_select.size();
float a=800;
while(q_select.next()){
list_data.append(q_select.value("bw_limit").toFloat()*10);
id.append(q_select.value("slice_id").toString());
list_name.append(q_select.value("slice_name").toString().trimmed());
a=a-q_select.value("bw_limit").toFloat()*10;
}
q_select.finish();
q_select.clear();
list_data.append(a);
list_name.append("空闲资源");
id.append("NULL");
//扇形
qreal factor = 0.05; //默认值
for (int i = 0; i < list_data.size(); i++)
{
QPieSlice* pie_slice= new QPieSlice(this);
//pie_slice->setLabelVisible(true);
pie_slice->setValue(list_data[i]);
// QString str_percent = QString::number(list_data[i],'f', 1).append("%");
// pie_slice->setLabel(str_percent);
pie_slice->setLabelVisible(false);
//调整标签角度
//占比10%以下切片的臂长
if ( list_data[i] < 15) {
pie_slice->setLabelArmLengthFactor(factor);
factor += 0.15; //参数视界面大小而定
//调整起始、结束角度. 目的是将数值较小的区域调整到右下角
if (pie_series1->pieStartAngle() < 135) {
pie_series1->setPieStartAngle(135);
pie_series1->setPieEndAngle(360 + 135);}}
if(list_name[i]=="空闲资源"){
pie_slice->setColor("#C0C0C0");
pie_slice->setLabelColor("#C0C0C0");
pie_slice->setBorderColor("#C0C0C0");
}
if(id[i]=="1"){
pie_slice->setColor("#FF6384");
pie_slice->setLabelColor("#FF6384");
pie_slice->setBorderColor("#FF6384");
}
//....
pie_series1->append(pie_slice);
}
//图表视图
QChart* chart = new QChart;
chart->setTitle("带宽资源分配图(%)<br>\n\n\n\n总带宽:800M");
//标题字体
QFont font = qApp->font();
font.setBold(true);
font.setPointSize(16);
chart->setTitleFont(font);
//加入饼图
chart->addSeries(pie_series1);
chart->setAnimationOptions(QChart::SeriesAnimations);
QList<QLegendMarker*> list_market=chart->legend()->markers(pie_series1);
for (int i = 0; i < list_data.size(); i++)
{
QString label=list_name[i]+" "+"("+QString::number(list_data[i]/8,'f', 1).append("%")+QString(",%1M)").arg(list_data[i]);
QString wrappedLabel = label.replace(QString(" "), QString("<br>")); // 将空格替换为换行符
list_market[i]->setLabel(QString("<html>%1</html>").arg(wrappedLabel));
}
chart->setBackgroundRoundness(0); // 取消背景圆角效果
chart->setMargins(QMargins(0, 10, 0, 0));
chart->layout()->setContentsMargins(0, 0, 0, 0); // 取消绘图区域的边距
//图例
chart->legend()->setAlignment(Qt::AlignRight);
chart->legend()->setBackgroundVisible(false);
ui->pie_1->setChart(chart); // 饼状图在chart上显示
}
柱状图:
在ui界面上添加QChartView 命名为:chartView_UE
void MainWindow::show_UE()
{
QBarSeries series = new QBarSeries(this);
//遍历数据库
QSqlQuery q_select(db);
q_select.prepare("SELECT * FROM slice_v2 WHERE TRIM(status)='11'");
q_select.setForwardOnly(true);
q_select.exec(); //运行数据库
//柱状
int row=0;
while (q_select.next()){
int num=q_select.value("num_ue").toInt();
QString id=q_select.value("slice_id").toString();
QBarSet *set = new QBarSet(q_select.value("slice_name").toString(),this);
*set << num; //向柱状切片i添加用户数量
if(id=="1"){
set->setLabelColor("#FF6384");
set->setColor("#FF6384");
}
if(id=="2"){
set->setLabelColor("#CC66FF");
set->setColor("#CC66FF");
series->append(set);
row++;
}
q_select.finish();
q_select.clear();
QChart *chart = new QChart();//创建图表
chart->addSeries(series);//序列添加到图表
chart->setTitle("切片支持接入终端数量(个)");//设置图表标题
// chart->setAnimationOptions(QChart::SeriesAnimations);//序列动态
QValueAxis *axisY = new QValueAxis(); //y轴
axisY->setGridLineVisible(true);
axisY->setTickCount(6); // 设置刻度数为 6
axisY->setRange(0, 10);
chart->addAxis(axisY, Qt::AlignLeft);
series->attachAxis(axisY);
series->setLabelsPosition(QAbstractBarSeries::LabelsOutsideEnd);//用户数量显示在柱形图外部上端
series->setLabelsVisible(true);
series->setBarWidth(0.2);
chart->legend()->setVisible(true);
chart->legend()->setAlignment(Qt::AlignBottom);
ui->chartView_UE->setChart(chart);//图表添加到场景
ui->chartView_UE->setRenderHint(QPainter::Antialiasing);
}
折线图:
在ui界面上添加QChartView 命名为:chartView_delay
//设置坐标轴和图表
void MainWindow::init_delay() //视频时延chartview图配置
{
QList <QString> str;
QList <QString> id;
QSqlQuery q_select(db);
q_select.prepare("SELECT * FROM slice_v2 WHERE TRIM(status)='11'");
q_select.setForwardOnly(true);
q_select.exec(); //运行数据库
//-------------建横纵坐标轴并设置显示范围------------//
axisX1 = new QDateTimeAxis();
axisY1 = new QValueAxis();
axisX1->setTitleText("时间(s)");
axisY1->setTitleText("时延(ms)");
axisX1->setFormat("hh:mm:ss");
axisX1->setMin(QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch()));
axisX1->setMax(QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch()+600000));
axisY1->setMin(0);
AXIS_MAX_X1=QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch()+600000);
axisY1->setMax(AXIS_MAX_Y1);
delay_lineseries.clear();
chart1 = new QChart(); // 创建图表对象
chart1->addAxis(axisY1, Qt::AlignLeft); // 将Y轴添加到图表上
chart1->addAxis(axisX1, Qt::AlignBottom); // 将X轴添加到图表上
for(int i=0;i<Max_slice_num;i++){//根据切片定义6条曲线
delay_lineseries.append(new QLineSeries());
}
for(int i=0;i<Max_slice_num;i++){
delay_lineseries[i]->setVisible(false); // 设置数据点可见
chart1->addSeries(delay_lineseries[i]); // 将曲线对象添加到图表上
delay_lineseries[i]->attachAxis(axisX1); // 曲线对象关联上X轴,此步骤必须在chart->addSeries之后
delay_lineseries[i]->attachAxis(axisY1);
}
chart1->setAnimationOptions(QChart::SeriesAnimations); // 动画:能使曲线绘制显示的更平滑,过渡效果更好看
ui->chartView_delay->setChart(chart1); // 将图表对象设置到graphicsView上进行显示
ui->chartView_delay->setRenderHint(QPainter::Antialiasing); // 设置渲染:抗锯齿,如果不设置那么曲线就显得不
}
//更新曲线数据和数据坐标
void MainWindow::show_delay(QList<QString>list_id,QList<float>list_delay,QList<QString>list_name) //显示视频时延数据和折线图
{
for(int i=0;i<delay_lineseries.size();i++){
if(QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch()) > AXIS_MAX_X1){
chart1->axes(Qt::Horizontal).back()->setRange(QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch()-Max_time*1000),QDateTime::fromMSecsSinceEpoch(QDateTime::currentDateTime().toMSecsSinceEpoch())); // 更新X轴范围
}
// 检查数据点数量是否超过600
if (delay_lineseries[i]->count() > Max_time) {
// 计算需要移除的数据点数量
int removeCount = delay_lineseries[i]->count() - Max_time;
// 移除之前的数据点
delay_lineseries[i]->removePoints(0, removeCount);
}
}
for(int i=0;i<Max_slice_num;i++){
delay_lineseries[i]->setVisible(false); }
for(int i=0;i<Max_slice_num;i++){
if(list_id[i]!="0"){
delay_lineseries[i]->setVisible(true);
delay_lineseries[i]->setColor(list_color[i]);
delay_lineseries[i]->setUseOpenGL(true); //缓解数据过大时的卡顿
delay_lineseries[i]->setName(list_name[i]);
delay_lineseries[i]->append(QDateTime::currentDateTime().toMSecsSinceEpoch(), list_delay[i]);
}
}
for(int i=0;i<Max_slice_num;i++){
if(list_id[i]=="0")
delay_lineseries[i]->clear();
}
}