首先附上效果图。Qt版本4.8.6,IDE:vs2008.柱状图可根据数据变化实时增减,支持修改刻度值范围,修改柱状图颜色和背景颜色。实现起来并不复杂,使用的都是一些非常常见的Qt类和函数,下面就来看看主要代码。
首先,背景的绘制并没有使用QSS,这样可以实时更改背景色。背景使用渐变,很简单。
其次是刻度线和刻度值的绘制稍微麻烦一点,因为刻度线要分别绘制单位刻度线,中位刻度线和主刻度线。需要注意的是绘制的位置和刻度线需要梯度上升。
最后,绘制柱状图和柱状图背景都相对简单,只需要设置好柱状图所在的区域就能快速绘制。
主要部分源码如下:
#include "MeasuringBar.h"
#include
#include
#include
#include
#include
#define DEVIATION 0.0001 //浮点数比较精度
#define LINEHPERSITION 15 //刻度线水平位置参数
#define TEXTWIDTH 5 //刻度值高度参数
#define TEXTHEIGHT 4 //刻度值宽度参数
#define BARHPOSITION 35 //柱状图水平位置参数
MeasuringBar::MeasuringBar(QWidget *parent)
: QWidget(parent)
{
Init();
CreateConnection();
}
MeasuringBar::~MeasuringBar()
{
if(m_timer->isActive())
{
m_timer->stop();
}
}
void MeasuringBar::Init()
{
m_dMinValue = 0.0; //最小值
m_dMaxValue = 100.0; //最大值
m_dTargetValue = 0.0; //目标值
m_iPercision = 0; //精度值。小数点后几位
m_iLongStep = 10; //长刻度条步长
m_iShortStep = 1; //短刻度条步长
m_iSpace = 20; //间距
m_bAnimation = false; //是否启用动画
m_dAnimationStep = 0.5; //动画播放时步长
m_BGColorStart = QColor(100, 100, 100); //背景开始渐变色
m_BGColorEnd = QColor(60, 60, 60); //背景结束渐变色
m_LineColor = QColor(255, 255, 255); //线条颜色
m_BarBGColor = QColor(220, 220, 220); //柱状图背景色
m_BarColor = QColor(100, 184, 255); //柱状图颜色
m_bReverse = false; //是否倒退
m_dCurrentValue = 0.0; //当前值
m_timer = new QTimer(this);
m_timer->setInterval(10);
setFont(QFont("Arial", 8));
}
void MeasuringBar::CreateConnection()
{
connect(m_timer, SIGNAL(timeout()), this, SLOT(SltUpdateValue()));
}
void MeasuringBar::SltUpdateValue()
{
if(!m_bReverse) //柱状图向上增长
{
if(m_dCurrentValue > m_dTargetValue)
{
m_dCurrentValue = m_dTargetValue;
m_timer->stop();
}
else
{
m_dCurrentValue += m_dAnimationStep;
}
}
else //柱状图向下减少
{
if(m_dCurrentValue <= m_dTargetValue)
{
m_dCurrentValue = m_dTargetValue;
m_timer->stop();
}
else
{
m_dCurrentValue -= m_dAnimationStep;
}
}
update();
}
//绘制背景(渐变)
void MeasuringBar::DrawBackground(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen); //Qt::NoPen:不绘制任何边界线
//渐变
QLinearGradient bgGradient(QPointF(0, 0), QPointF(0, height()));
bgGradient.setColorAt(0.0, m_BGColorStart);
bgGradient.setColorAt(1.0, m_BGColorEnd);
painter->setBrush(bgGradient);
painter->drawRect(rect());
painter->restore();
}
//绘制刻度及刻度值
void MeasuringBar::DrawRuler(QPainter *painter)
{
painter->save();
painter->setPen(m_LineColor);
//绘制纵向标尺线
double initX = m_iSpace + LINEHPERSITION;
double initY = m_iSpace;
QPointF topPoint(initX, initY);
QPointF bottomPoint(initX, height()-m_iSpace);
painter->drawLine(topPoint, bottomPoint);
//绘制刻度
double length = height() - 2 * m_iSpace; //刻度线距离顶部和底部m_iSpace距离,所以它的长度就是这么多
double increment = length / (m_dMaxValue - m_dMinValue); //计算每一格移动多少
int longLineLength = 10; //长刻度线长
int shortLineLength = 7; //短刻度线长
//根据范围绘制刻度值
for(int i = static_cast
{
if(i % m_iLongStep == 0) //画最长刻度线
{
QPointF leftPoint(initX, initY);
QPointF rightPoint(initX + longLineLength, initY);
painter->drawLine(leftPoint, rightPoint); //绘制刻度线
QString strValue = QString("%1").arg(static_cast
double fontWidth = static_cast
//qDebug() << typeid(painter->fontMetrics().width(strValue)).name() << "-------";
double fontHeight = static_cast
QPointF textPoint(initX - fontWidth - TEXTWIDTH, initY + fontHeight / TEXTHEIGHT); //刻度值位置
painter->drawText(textPoint, strValue); //绘制刻度值
}
else
{
if(i % (m_iLongStep / 2) == 0) //刻度中位线长
{
shortLineLength = 7;
}
else //单位刻度线长
{
shortLineLength = 4;
}
QPointF leftPoint(initX, initY);
QPointF righPoint(initX + shortLineLength, initY); //刻度线位置
painter->drawLine(leftPoint, righPoint); //画刻度线
}
initY += increment * m_iShortStep; //刻度线向上移动
}
painter->restore();
}
//绘制柱状图背景
void MeasuringBar::DrawBarBackground(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
double initX = static_cast
QPointF topLeftPoint(initX, m_iSpace);
QPointF bottomRightPoint(width() - m_iSpace, height() - m_iSpace);
m_barRect = QRectF(topLeftPoint, bottomRightPoint); //柱状图所在区域
painter->setBrush(m_BarBGColor);
painter->drawRect(m_barRect);
painter->restore();
}
//绘制柱状图
void MeasuringBar::DrawBar(QPainter *painter)
{
painter->save();
painter->setPen(Qt::NoPen);
double barHeight = m_barRect.height();
double increment = barHeight / (m_dMaxValue - m_dMinValue); //增量
double initY = (m_dCurrentValue - m_dMinValue) * increment;
QPointF topLeftPoint(m_barRect.topLeft().x(), m_barRect.bottomLeft().y() - initY);
//qDebug() << "----------------" << m_barRect.bottomLeft().y();
QPointF bottomRightPoint(m_barRect.bottomRight());
QRectF currentRect(topLeftPoint, bottomRightPoint);
painter->setBrush(m_BarColor);
painter->drawRect(currentRect);
painter->restore();
}
//绘画事件
void MeasuringBar::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing); //反走样
DrawBackground(&painter);
DrawRuler(&painter);
DrawBarBackground(&painter);
DrawBar(&painter);
}
//设置刻度范围
void MeasuringBar::SetRange(double minValue, double maxValue)
{
if(m_dMinValue > m_dMaxValue) //最小值大于最大值,不合理
{
return;
}
m_dMinValue = minValue;
m_dMaxValue = maxValue;
if(m_dTargetValue < m_dMinValue || m_dTargetValue > m_dMaxValue)
{
SetTargetValue(m_dTargetValue);
}
update();
}
void MeasuringBar::SetRange(int minValue,int maxValue)
{
SetRange(static_cast
}
//设置最大最小值
void MeasuringBar::SetMaxValue(double maxValue)
{
SetRange(m_dMinValue, maxValue);
}
void MeasuringBar::SetMinVlaue(double minValue)
{
SetRange(minValue, m_dMaxValue);
}
//设置目标值
void MeasuringBar::SetTargetValue(double targetValue)
{
if(targetValue < m_dMinValue || targetValue > m_dMaxValue)
{
return;
}
if(targetValue > m_dTargetValue)
{
m_bReverse = false;
}
else if(targetValue < m_dTargetValue)
{
m_bReverse = true;
}
m_dTargetValue = targetValue;
emit TargetValueChanged(targetValue);
if(!m_bAnimation)
{
m_dCurrentValue = m_dTargetValue;
update();
}
else
{
m_timer->start();
}
}
void MeasuringBar::SetTargetValue(int targetValue)
{
SetTargetValue(static_cast
}
//设置精确度
void MeasuringBar::SetPercision(int percision)
{
if(percision <= 3 && m_iPercision != percision) //最大精确度为3
{
m_iPercision = percision;
update();
}
}
//设置长短刻度条步长
void MeasuringBar::SetLongStep(int longStep)
{
if(m_iShortStep > m_iLongStep) //短刻度步长不可超过长刻度步长
{
return;
}
if(m_iLongStep != longStep)
{
m_iLongStep = longStep;
update();
}
}
void MeasuringBar::SetShortStep(int shortStep)
{
if(m_iShortStep > m_iLongStep) //短刻度步长不能超过长刻度步长
{
return;
}
if(m_iShortStep != shortStep)
{
m_iShortStep = shortStep;
update();
}
}
//设置间距
void MeasuringBar::SetSpace(int space)
{
if(m_iSpace != space)
{
m_iSpace = space;
}
}
//设置是否使用动画显示
void MeasuringBar::SetUseAnimation(bool animation)
{
if(m_bAnimation != animation)
{
m_bAnimation = animation;
update();
}
}
void MeasuringBar::SetAnimationStep(double animationStep)
{
if(fabs(m_dAnimationStep - animationStep) > DEVIATION) //m_dAnimationStep != animationStep
{
m_dAnimationStep = animationStep;
update();
}
}
//设置背景颜色
void MeasuringBar::SetBackgroundColorStart(const QColor &BgColorStart)
{
if(m_BGColorStart != BgColorStart)
{
m_BGColorStart = BgColorStart;
update();
}
}
void MeasuringBar::SetBackgroundColorEnd(const QColor &BgColorEnd)
{
if(m_BGColorEnd != BgColorEnd)
{
m_BGColorEnd = BgColorEnd;
update();
}
}
//设置线条颜色
void MeasuringBar::SetLineColor(const QColor &lineColor)
{
if(m_LineColor != lineColor)
{
m_LineColor = lineColor;
update();
}
}
//设置柱状图背景颜色
void MeasuringBar::SetBarBgColor(const QColor &barBgColor)
{
if(m_BarBGColor != barBgColor)
{
m_BarBGColor = barBgColor;
update();
}
}
//设置柱状图颜色
void MeasuringBar::SetBarColor(const QColor &barColor)
{
if(m_BarColor != barColor)
{
m_BarColor = barColor;
update();
}
}
如需整个工程请见:https://download.csdn.net/download/dzhongjie/11099810