Qt使用QWT绘制柱状图详解

目录
  • 1:设置QChart的整体背景色
  • 2:设置有效区域的背景色
  • 3:设置X、Y坐标轴数据
  • 4:设置网格线
  • 5:插入实际数据
  • 6:X轴刻度值优化
  • 7:设置X轴文本偏移
  • 8:设置每个柱状体的宽度
  • 9:设置每个柱状体的偏移量
  • 10:修改鼠标的显示状态

有的时候我们会遇到这样一种功能,需要在柱状图中显示不同颜色的柱状体,每个主状态代表的状态不同,那么如果只是用简单的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);

到此这篇关于Qt使用QWT绘制柱状图详解的文章就介绍到这了,更多相关Qt QWT柱状图内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python3+PyQt5实现柱状图

    本文通过Python3+pyqt5实现了python Qt GUI 快速编程的16章的excise例子. #!/usr/bin/env python3 import random import sys from PyQt5.QtCore import (QAbstractListModel, QAbstractTableModel, QModelIndex, QSize, QTimer, QVariant, Qt,pyqtSignal) from PyQt5.QtWidgets import (

  • Qt创建并显示柱状图的方法

    创建一个简单的柱状图 第一步:创建一个QBarSet对象:QBarSet类代表条形图中的一组条形. QBarSet *set0 = new QBarSet("Jane"); QBarSet *set1 = new QBarSet("John"); QBarSet *set2 = new QBarSet("Axel"); QBarSet *set3 = new QBarSet("Mary"); QBarSet *set4 = n

  • Qt使用QWT绘制柱状图详解

    目录 1:设置QChart的整体背景色 2:设置有效区域的背景色 3:设置X.Y坐标轴数据 4:设置网格线 5:插入实际数据 6:X轴刻度值优化 7:设置X轴文本偏移 8:设置每个柱状体的宽度 9:设置每个柱状体的偏移量 10:修改鼠标的显示状态 有的时候我们会遇到这样一种功能,需要在柱状图中显示不同颜色的柱状体,每个主状态代表的状态不同,那么如果只是用简单的QChart是难以实现的. QT中提供了一个叫做QWT的库.QWT,全称是Qt Widgets for Technical Applica

  • Python matplotlib 绘制散点图详解建议收藏

    目录 前言 1. 散点图概述 什么是散点图? 散点图使用场景 绘制散点图步骤 案例展示  2. 散点图属性 设置散点大小 设置散点颜色 设置散点样式 设置透明度 设置散点边框 3. 添加折线散点图 4. 多类型散点图 5. 颜色条散点图 6. 曲线散点图 总结 前言 我们在matplotlib模块学习中,发现有常用的反映数据变化的折线图,对比数据类型差异的柱状图和反应数据频率分布情况的直方图. 其实在数据统计图表中,有一种图表是散列点分布在坐标中,反应数据随着自变量变化的趋势. 本期,我们将详细

  • Python利用Matplotlib绘制图表详解

    目录 前言 折线图绘制与显示 绘制数学函数图像 散点图绘制 绘制柱状图 绘制直方图 饼图 前言 Matplotlib 是 Python 中类似 MATLAB 的绘图工具,如果您熟悉 MATLAB,那么可以很快的熟悉它. Matplotlib 提供了一套面向对象绘图的 API,它可以轻松地配合 Python GUI 工具包(比如 PyQt,WxPython.Tkinter)在应用程序中嵌入图形.与此同时,它也支持以脚本的形式在 Python.IPython Shell.Jupyter Notebo

  • Python pyecharts绘制条形图详解

    目录 一.简介 二.整理数据 1.配置主题 2.柱状图 Bar - Bar_base_dict_config 3.样例数据 Faker.choose() 4.滚动条 Bar - Bar_datazoom_slider 5.鼠标移动效果 Bar - Bar_datazoom_inside 6.显示最值 Bar - Bar_markpoint_type 7.改变滚动条在侧面 Bar - Bar_datazoom_slider_vertical 8.多个Y轴 9.直方图 Bar - Bar_histo

  • Python matplotlib 绘制散点图详解建议收藏

    目录 前言 1. 散点图概述 什么是散点图? 散点图使用场景 绘制散点图步骤 案例展示  2. 散点图属性 设置散点大小 设置散点颜色 设置散点样式 设置透明度 设置散点边框 3. 添加折线散点图 4. 多类型散点图 5. 颜色条散点图 6. 曲线散点图 总结 前言 我们在matplotlib模块学习中,发现有常用的反映数据变化的折线图,对比数据类型差异的柱状图和反应数据频率分布情况的直方图. 往期内容速看 Python用 matplotlib 绘制柱状图 Python matplotlib底层

  • Android RecyclerChart其它图表绘制示例详解

    目录 正文 1. 心电图 2. 睡眠图 正文 之前章节介绍了RecyclerChart 中一些通用的图表的相关绘制逻辑,本章节介绍两种Special的Chart的绘制,一种是心电图,一种是睡眠图.首先我们来看下心电图EcgChart的绘制. 1. 心电图 EcgChart 跟LineChart形态上是相似的,但是EcgChart的点相对于LineChart密集的多,之前的LineChart相当于每个RecyclerView的Itemview 中的Model对应的value值,而心电图的ItemD

  • Android view绘制流程详解

    绘制流程 measure 流程测量出 View 的宽高尺寸. layout 流程确定 View 的位置及最终尺寸. draw 流程将 View 绘制在屏幕上. Measure 测量流程 系统是通过 MeasureSpec 测量 View 的,在了解测量过程之前一定要了解这个 MeasureSpec . MeasureSpec MeasureSpec 是一个 32 位的 int 值打包而来的,打包为 MeasureSpec 主要是为了避免过多的对象内存分配. 为了方便操作,MeasureSpec

  • C/C++ Qt数据库SqlRelationalTable关联表详解

    在上一篇博文中详细介绍了SqlTableModle组件是如何使用的,本篇博文将介绍SqlRelationalTable关联表组件,该组件其实是SqlTableModle组件的扩展类,SqlRelationalTable组件可以关联某个主表中的外键,例如将主表中的某个字段与附加表中的特定字段相关联起来,QSqlRelation(关联表名,关联ID,名称)就是用来实现多表之间快速关联的. 首先我们创建两张表,一张Student表存储学生名字以及学生课程号,另一张Departments存储每个编号所对

  • Qt+OpenCV实现目标检测详解

    目录 一.创建项目&UI设计 二.代码与演示 演示效果 拓展阅读 一.创建项目&UI设计 创建项目,UI设计如下 文件类型判断 简单的判断文件类型 QString file("sample.jpg"); if (file.contains(".jpg") || file.contains(".bmp") || file.contains(".png")) qDebug()<<"这是图片.&

  • Python matplotlib plotly绘制图表详解

    目录 一.整理数据 二.折线图 三.散点图 四.饼图 五.柱形图 六.点图(设置多个go对象) 七.2D密度图 八.简单3D图 一.整理数据 以300部电影作为数据源 import pandas as pd cnboo=pd.read_excel("cnboNPPD1.xls") cnboo import seaborn as sns import numpy as np import matplotlib as mpl from matplotlib import pyplot as

随机推荐