写点什么

Qt|QWT 绘制柱状图一类多种颜色

  • 2022 年 7 月 13 日
  • 本文字数:3620 字

    阅读完需:约 12 分钟

Qt|QWT绘制柱状图一类多种颜色

有的时候我们会遇到这样一种功能,需要在柱状图中显示不同颜色的柱状体,每个主状态代表的状态不同,那么如果只是用简单的 QChart 是难以实现的。


QT 中提供了一个叫做 QWT 的库。QWT,全称是 Qt Widgets for Technical Applications,是一个基于 LGPL 版权协议的开源项目,可生成各种统计图。它为具有技术专业背景的程序提供 GUI 组件和一组实用类,其目标是以基于 2D 方式的窗体部件来显示数据,数据源以数值,数组或一组浮点数等方式提供,输出方式可以是 Curves(曲线),Slider(滚动条),Dials(圆盘),Compasses(仪表盘)等等。该工具库基于 Qt 开发,所以也继承了 Qt 的跨平台特性。


下面介绍的实现效果如下所示:


主要难实现功能:


1:柱状图实现了一类下有多种颜色显示,

2:文本、每个柱状体可以进行偏移

3:修改柱状体的宽度

4:修改有效图表的鼠标显示状态


QWT 中给的 example 例子也可以实现一种类型对应多种颜色的柱状图,但是,无法实现文字以及柱状图的偏移。

很明显,当前效果图的文本以及柱状图显示在了网格中间。如果有博友想实现和我一样的效果,那就请继续往下看。

该效果我是在 example 的例子基础上进行改进的,其中基本框架不变,在我看来,没有实现不了的功能,只有你对这个库的熟悉程度,该功能代码简单,但是还是耗费了我三天的时间。

下面我进行功能讲解

1:设置 QChart 的整体背景色

m_pChart->setAutoFillBackground(true);m_pChart->setFrameStyle(QFrame::NoFrame);m_pChart->setLineWidth(0);m_pChart->setPalette(QColor(255, 255, 255));
复制代码

2:设置有效区域的背景色

QwtPlotCanvas *canvas = new QwtPlotCanvas();canvas->setFrameStyle(QFrame::NoFrame);m_pChart->setCanvas(canvas);
复制代码

3:设置 X、Y 坐标轴数据

当前 X 轴显示的是 0-30 条数据,Y 轴是 0-8 条数据

m_pChart->setAxisScale(QwtPlot::xBottom, 0, 30);m_pChart->setAxisMaxMajor(QwtPlot::xBottom, 30);m_pChart->setAxisMaxMinor(QwtPlot::xBottom, 0);m_pChart->setAxisScale(QwtPlot::yLeft, 0, 8);m_pChart->setAxisMaxMajor(QwtPlot::yLeft, 6);m_pChart->setAxisMaxMinor(QwtPlot::yLeft, 2);
复制代码

这是设置 X、Y 轴的基本设置,如果想要设置字体呢?如下:

QFont fontX;fontX.setFamily(QStringLiteral("微软雅黑"));fontX.setPointSize(12);m_pChart->setAxisFont(QwtPlot::xBottom, fontX);
复制代码

在此处,我只是显示了 X 轴的字体设置,Y 轴同理,就不显示了。

4:设置网格线

QwtPlotGrid *grid = new QwtPlotGrid;grid->setMajorPen(QColor(193, 193, 193), 1, Qt::SolidLine);grid->attach(m_pChart);
复制代码

如果按照当前代码设置网格时,大家会发现,中间刻度没有网格线显示,效果如下图所示:


如果有需要类似功能的,仅用上面代码就可以实现。但是,有人却说,想要中间刻度也有网格线显示,那么,使用以下代码实现

QwtPlotGrid *grid = new QwtPlotGrid;grid->enableXMin(true);grid->enableYMin(true);grid->setMajorPen(QColor(193, 193, 193), 1, Qt::SolidLine);grid->setMinorPen(QColor(193, 193, 193), 1, Qt::SolidLine);grid->attach(m_pChart);
复制代码

强制显示网格线的中间刻度网格线。经过设置之后,就和 1-1 图一致,根据大家需求自行设置。

5:插入实际数据

当前操作是在柱状图中插入数据,可以对每一条柱状体进行颜色设置,实现代码:

m_pChartItemAir = new CustomBarChartItem();
QStringList listPData;QVector<double> vetSample;for (int i = 0; i < vetColorData.size(); i++){ ColorData stInfo = vetColorData[i]; vetSample.append(stInfo.nNum);
QString sText = QString::number(i+1, 10); listPData.append(sText);
QColor color = stInfo.color; m_pChartItemPress->InsertBarData(sText, color);}//数据插入之后,进行绑定m_pChartItemPress->setSamples(vetSample);m_pChartItemPress->attach(m_pChartPress);
复制代码

CustomBarChartItem 该类是我对 QwtPlotBarChart 类的重写。

其中,InsertBarData()该函数设置了每个柱状体对应的不同颜色值。

插入数据之后,进行数据绑定。

InsertBarData()中调用 QwtPlotBarChart::itemChanged(),让类中自动调用 specialSymbol() 该函数进行颜色值更改

QwtColumnSymbol * CustomBarChartItem::specialSymbol(int sampleIndex, const QPointF&) const{	//TODO: 我们希望每个条形都有不同的颜色	CustomBarChartColumnSymbol *symbol = new CustomBarChartColumnSymbol(QwtColumnSymbol::Box);	symbol->setFrameStyle(QwtColumnSymbol::NoFrame);	symbol->SetColumnMoveLen(m_nMoveLen);	QColor currentColor(Qt::white);	QString sHit = "";	if ((sampleIndex >= 0) && (sampleIndex < m_listColor.size()))	{	    currentColor = m_listColor[sampleIndex];	    sHit = m_listLabel.at(sampleIndex);	}	symbol->setPalette(currentColor);	return symbol;}
复制代码

实现改变颜色的核心代码是:symbol->setPalette(currentColor);

6:X 轴刻度值优化

CustomBarChartScaleDraw *pScaleDraw = new CustomBarChartScaleDraw(Qt::Orientation::Horizontal, listPressLabel);pScaleDraw->SetXBottomMoveLens(10);m_pChart->setAxisScaleDraw(QwtPlot::xBottom, pScaleDraw);
复制代码

其中,setAxisScaleDraw 的第一个参数是控制,是 X 轴?Y 轴

当前 CustomBarChartScaleDraw 类是我对 QwtScaleDraw 的重写

7:设置 X 轴文本偏移

第 6 步骤中,SetXBottomMoveLens()函数实现的功能就是对 X 轴文本进行偏移。

8:设置每个柱状体的宽度

setLayoutPolicy(FixedSampleSize);

setLayoutHint(nWidth); //设定了柱状体的宽度

9:设置每个柱状体的偏移量

写到这里,大家会发现,运行之后,效果差强人意,如图所示。


每个柱状图都在网格的垂直线上,而且第一位还显示不全,看起来很是不舒服。下面需要设置对柱状图的偏移,这个功能可真是不好改,改了一天才弄好 -_-||


修改柱状图的偏移需要在 QwtColumnSymbol 类中进行修改,那么重写该类,叫做 CustomBarChartColumnSymbol 这个名字,对 draw 函数进行重载

virtual void draw(QPainter *painter, const QwtColumnRect &rect) const;
复制代码

加入 QWT 源码之后,可以查看到 draw 函数的实现,我们需要仿照源码中进行实现,只是修改下显示位置。因为在 QwtColumnSymbol 中,修改柱状图区域的类未对外开放,所以,只能依靠 draw 的 QwtColumnRect 类进行修改。

当 draw 在调用 drawBox 函数时,需要将修改的 QwtColumnRect 的区域传给父类,这样就会修改显示位置。

直接上代码更直接一些

void CustomBarChartColumnSymbol::draw(QPainter *painter, const QwtColumnRect &rect) const{	QwtColumnRect rectNew = rect;	if (m_nMoveLens > 0)	{		int nMin = rectNew.hInterval.minValue() + m_nMoveLens;		rectNew.hInterval.setMinValue(nMin);		int nMax = rectNew.hInterval.maxValue() + m_nMoveLens;		rectNew.hInterval.setMaxValue(nMax);	}		painter->save();	switch (this->style())	{	case QwtColumnSymbol::Box:	{		drawBox(painter, rectNew);	}	break;	default:;	}	painter->restore();}
复制代码

修改的位置,其实是对 QwtColumnRect 的 QwtInterval hInterval; 进行修改。因为实现的是需要对 X 轴进行偏移,所以只对该参数进行修改,其余按照父类的 draw 进行实现。


CustomBarChartColumnSymbol 的代码实现

CustomBarChartColumnSymbol::CustomBarChartColumnSymbol(Style sStyle/* = NoStyle*/) :QwtColumnSymbol(sStyle){	m_nMoveLens = 0;}
CustomBarChartColumnSymbol::~CustomBarChartColumnSymbol(){
}
void CustomBarChartColumnSymbol::SetColumnMoveLen(int nMoveLen){ m_nMoveLens = nMoveLen;}
void CustomBarChartColumnSymbol::draw(QPainter *painter, const QwtColumnRect &rect) const{ QwtColumnRect rectNew = rect; if (m_nMoveLens > 0) { int nMin = rectNew.hInterval.minValue() + m_nMoveLens; rectNew.hInterval.setMinValue(nMin); int nMax = rectNew.hInterval.maxValue() + m_nMoveLens; rectNew.hInterval.setMaxValue(nMax); } painter->save(); switch (this->style()) { case QwtColumnSymbol::Box: { drawBox(painter, rectNew); } break; default:; } painter->restore();}
复制代码

其中,偏移位置的大小是由 SetColumnMoveLen 进行设置的。

10:修改鼠标的显示状态

canvas->setCursor(Qt::ArrowCursor); //修改鼠标在画布上的显示方式,系统默认是十字架形状
复制代码

在实现过程中,大家会发现,实现的网格效果和我的有些不一致,网格线并没有呈现闭合状态,可以使用以下代码实现

m_pChart->plotLayout()->setAlignCanvasToScales(true);
复制代码

以上最难实现的功能实现方法已经全部列举了,如果需要查看源代码的,可以使用以下链接进行下载:QWT主状态显示


今天的更新到这里就结束了!

我是中国好公民 st,一名 C++开发程序媛~

发布于: 刚刚阅读数: 4
用户头像

书山有路勤为径,学海无涯苦作舟 2022.07.01 加入

擅长语言:C++ 涉及语言:Python

评论

发布
暂无评论
Qt|QWT绘制柱状图一类多种颜色_qt_中国好公民st_InfoQ写作社区