1.以在UI上添加柱状图的类为例(Histogram)
cpp
#ifndef STUDY_HISTOGRAM_H
#define STUDY_HISTOGRAM_H
#include <QVector>
#include <QWidget>
// 前向声明
QT_BEGIN_NAMESPACE
class QColor;
class QRect;
class QString;
class QPaintDevice;
QT_END_NAMESPACE
class Study_HistogramItem
{
public:
QString m_Name;
qreal m_Value;
QColor m_PillarColor;
QRect m_PillarRect;
};
class Study_Histogram : public QWidget
{
public:
Study_Histogram( QWidget* parent = 0 );
//方法
void Study_AddItem( QString name, qreal value,
QColor pillarColor );
void Study_SetMaxValue( quint32 maxValue ); // 设置最大值,以便绘图
void Study_Clear(); // 清空所有已添加的Item
void Study_Paint( QPaintDevice* pDevice ); // 绘图
protected:
//刷新页面
void paintEvent(QPaintEvent *);
private:
void Study_DrawAxis( QPaintDevice* pDevice, QPainter* pPainter ); // 绘制坐标轴
void Study_DrawPillars( QPaintDevice* pDevice, QPainter* pPainter ); // 绘制柱子
void Study_DrawText( QPainter *pPainter ); // 绘制文字
void Study_DrawScale( QPaintDevice* pDevice, QPainter* pPainter ); // 绘制刻度
//类属性
enum Study_HistogramOptions
{
blankWidth = 64, // 两个柱子间的空格大小
pillarIndent = 0, // 首个柱子缩进的大小
xAxisOffset = 16, // X轴的偏移(相对于左边界)
yAxisOffset = 16, // Y轴的偏移(相对于下边界)
textRectHeight = 32 // 文字矩形框的高
};
qreal m_Study_axValue;
QVector<Study_HistogramItem> m_Study_VecItems;
};
#endif // STUDY_HISTOGRAM_H
2.饼图的属性:最大值,单个柱形的信息
在饼图类的构造函数中设置默认的信息:清空之前的柱形组数据
cpp
Study_Histogram::Study_Histogram(QWidget *parent)
{
m_Study_VecItems.clear( );
}
3.饼图的方法(函数):添加柱形,设置最大值,清空信息
添加柱形:
cpp
void Study_Histogram::Study_AddItem(QString name, qreal value, QColor pillarColor)
{
//先创建一个柱状信息的实例
Study_HistogramItem item;
item.m_Name = name;
item.m_Value = value;
item.m_PillarColor = pillarColor;
item.m_PillarRect = QRect( );
//将此实例添加到属性QVector中
m_Study_VecItems.push_back( item );
}
设置最大值:
cpp
void Study_Histogram::Study_SetMaxValue(quint32 maxValue)
{
//将参数传入类属性中
m_Study_maxValue = maxValue;
}
清空信息:
cpp
void Study_Histogram::Study_Clear()
{
//把柱状图信息容器清空
m_Study_VecItems.clear();
}
4.某些属性的关联数据(单个柱形信息包括:名字,数据,颜色等)
cpp
在类的定义.h文件中,定义了结构体Study_HistogramItem
供给属性QVector<Study_HistogramItem> m_Study_VecItems;
5.paintEvent进行自动刷新
cpp
void Study_Histogram::paintEvent(QPaintEvent *)
{
Study_Paint(this);
}
void Study_Histogram::Study_Paint(QPaintDevice *pDevice)
{
QPainter painter( pDevice ); //
Study_DrawAxis( pDevice, &painter );// 绘制坐标轴
Study_DrawPillars( pDevice, &painter );// 绘制柱子
Study_DrawText( &painter );// 绘制文字
Study_DrawScale( pDevice, &painter );// 绘制刻度
}
绘制坐标轴/柱子/文字/刻度(pPainter->drawText)
cpp
void Study_Histogram::Study_DrawAxis(QPaintDevice *pDevice, QPainter *pPainter)
{
//坐标轴
pPainter->drawLine( yAxisOffset, 0, yAxisOffset, pDevice->height( ) );
pPainter->drawLine( 0, pDevice->height( ) - xAxisOffset,
pDevice->width( ), pDevice->height( ) - xAxisOffset );
}
void Study_Histogram::Study_DrawPillars(QPaintDevice *pDevice, QPainter *pPainter)
{
//柱子
if ( m_Study_VecItems.size( ) == 0 ) return;
//const quint32 blankWidth = 64; // 柱子间空格宽
quint32 pillarWidth = ( pDevice->width( ) - yAxisOffset - pillarIndent
- quint32( m_Study_VecItems.size( ) - 1 ) * blankWidth )
/ m_Study_VecItems.size( ); // 柱子的宽
// 绘制因子。绘制因子在绘制柱子的时候起着重要作用。
// 根据比例公式:
// pDevice->width( ) - xAxisOffset pillarHeight
// --------------------------------- = --------------------
// MaxValue m_VecItem[0].value
// 求出pillarHeight的值,但是左边的部分我们可以看作是一个绘制因子heightFact记录下来。
// 计算时可以节约时间。
qreal heightFact = qreal( pDevice->height( ) - xAxisOffset ) / m_Study_maxValue;
for ( int i = 0; i < m_Study_VecItems.size( ); ++i )
{
quint32 pillarHeight = m_Study_VecItems[i].m_Value * heightFact;
int leftUpX = yAxisOffset + pillarIndent + i * ( pillarWidth + blankWidth );
int leftUpY = pDevice->height( ) - xAxisOffset - pillarHeight;
QRect& rect = m_Study_VecItems[i].m_PillarRect;
rect.setRect( leftUpX, leftUpY, pillarWidth, pillarHeight );
pPainter->setPen( QPen( m_Study_VecItems[i].m_PillarColor ) );
pPainter->setBrush( QBrush( m_Study_VecItems[i].m_PillarColor ) );
pPainter->drawRect( rect );
}
}
void Study_Histogram::Study_DrawText(QPainter *pPainter)
{
// 已经可以保证m_VecItems.[i].m_Rect.isNull( )为假
// 即柱子所在的矩形框是一个有效的矩形框
pPainter->setPen( QPen( QColor( 0, 0, 0 ) ) );
for ( int i = 0; i < m_Study_VecItems.size( ); ++i )
{
QRect rect( m_Study_VecItems[i].m_PillarRect.left( ) - blankWidth / 2,
m_Study_VecItems[i].m_PillarRect.top( ) - textRectHeight,
m_Study_VecItems[i].m_PillarRect.width( ) + blankWidth,
textRectHeight );
const QString& text = QString( "%1(%2)" )
.arg( m_Study_VecItems[i].m_Name ).arg( m_Study_VecItems[i].m_Value );
pPainter->drawText( rect, Qt::AlignCenter, text );
}
}
void Study_Histogram::Study_DrawScale(QPaintDevice *pDevice, QPainter *pPainter)
{
// 名词解释 MSWidth = Marked Scale Width,刻度宽
// MSHeight = Marked Scale Height 刻度高
const quint32 MSWidth = 100;
const quint32 MSHeight = textRectHeight;
const quint32 heightInterval
= ( pDevice->height( ) - xAxisOffset ) / 4;
for ( int i = 0; i < 4; ++i )
{
QRect rect( 0,
i * heightInterval,
MSWidth,
MSHeight );
pPainter->drawLine( yAxisOffset - 2,
i * heightInterval,
yAxisOffset + 2,
i * heightInterval );
pPainter->drawText(
rect, Qt::AlignLeft, QString( "%1" )
.arg( m_Study_maxValue * ( 4 - i ) / 4 ) );
}
}
使用:直接用ui -> ...(提升的UI名) -> 类方法,此处ui->widget_histogram已经在UI中提升为Study_Histogram
cpp
ui->widget_histogram->Study_SetMaxValue(100);
ui->widget_histogram->Study_AddItem("name1",35,"red");
ui->widget_histogram->Study_AddItem("name2",45,"green");
ui->widget_histogram->Study_AddItem("name3",55,"black");
ui->widget_histogram->Study_AddItem("name4",75,"red");
效果: