正好遇到需要在qt里进行一个程序统计图的绘制,查了下qt的文档本来以为应该有存在一个类似的统计类.. 结果失望了。于是想到的有几个办法,第一是重写一些绘图像paint一样的函数.. 但是就需要画太多的东西了。。 于是就只能找一下有木有第三方的东西了。对了,qt其实有这种的,但是呢,那是企业版就是要付费的。然后找了找,也就qwt支持的还比较好,有比较多的功能和讲解,虽然说是用不到这么多的啦。
配置的话,直接官网下源码,然后利用pro编译就可以了,源码中已经包含了许多的example源码,编译出来之后,在编译的目录下的example 之类的下面有bin文件夹,里面就有例子的执行文件了。这些例子和源码能够让你学到很多使用的方法了,直接看例子算是比较简单的方法了,那个是你要实现的东西,那么你就参考那个的源码就是了。
然后qt使用的话,在qwt编译好之后会在编译完成后的目录下的lib文件夹下面(也许会有变化),有qwt.lib,qwtd.lib,qwtmathml.lib,qwtmathmld.lib这几个文件,就是你需要在程序pro里面进行添加的了(带不带d是区别debug,release的应该知道了。)在项目目录下直接建个lib文件夹简单快捷:
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -lqwt -lqwtmathml
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -lqwtd -lqwtmathmld
else:unix: LIBS += -L$$PWD/lib/ -lqwt -lqwtmathml
INCLUDEPATH += $$PWD/
DEPENDPATH += $$PWD/
win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/libqwt.a $$PWD/lib/libqwtmathml.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/libqwtd.a $$PWD/lib/libqwtmathmld.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/lib/qwt.lib $$PWD/lib/qwtmathml.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/lib/qwtd.lib $$PWD/lib/qwtmathmld.lib
else:unix: PRE_TARGETDEPS += $$PWD/lib/libqwt.a $$PWD/lib/libqwtmathml.a
然后还需要吧qwt的文件包进来,qwt源码目录下已经有这个include的文件了,在src下面,吧pri include进你的程序pro,然后根据里面的注释去删减或者修改一些根据需要变动的东西就好了:include(src/qwt/src.pri) 比如cpp文件不需要的就在这里注释掉或者删掉就好了。
其实自己弄弄就知道了,然后就是使用的了,对于这个东西,我们根据需要,比如我用到的就不多,所以只贴用到的东西了。
用到的这个资料其实很少,但其实就是需要多看看文档,也不是特别的复杂,特别多,稍微看多几个你可能用到的就好的了:http://qwt.sourceforge.net/annotated.html
QwtPlot:
这个是一个基本的类的,就是一个2d的容器,所有的继承自QwtPlotItem的部件都能在他的canvas上面显示,包括:数据的弧线 (QwtPlotCurve), 标记 (QwtPlotMarker), 布局 (QwtPlotGrid)等等,example里面有个最简单的例子simpleplot当成一个参考。
QwtPlotCanvas:
这个就是基于QWTplot上面的画布了,就是坐标啊 线啊这些东西东都会在这上面来显示。
QwtLegend:
这是一个图例的类,就是决定显示的图例的样式的。具体参考文档咯~
QwtPlotGrid:
这个类是图标的一个表格布局,比如网格线的样式等等。
QwtPlotCurve:
这个就是最基本的那个表格的统计的数据曲线了。
QwtSymbol:
这个是数据曲线上的数据点的样式
QwtPlotPicker:
这个类比较多的功能,就是在画布上执行的选择的处理,我这里用到的是鼠标在画布上的时候需要显示对应的数值,也需要继承这个类来实现。
然后就是简单的代码了,首先是吧继承的要实现鼠标移动时显示当前点数据的功能:
class MyPicker: public QwtPlotPicker
{
public:
MyPicker( QWidget *canvas ):
QwtPlotPicker( canvas )
{
//数据什么时候显示
setTrackerMode( QwtPlotPicker::AlwaysOn );
//数据获取的坐标轴的选择
setAxis(QwtPlot::xBottom, QwtPlot::yLeft);
}
protected:
//这个重载实现的是鼠标移动显示的数据
virtual QwtText trackerTextF( const QPointF &pos ) const
{
QString s;
s.sprintf( " 数值:%.4f ", pos.y() );
QwtText text( s );
text.setColor( Qt::white );
//显示的样式的东西:
QColor c(Qt::gray);
text.setBorderPen( QPen( c ) );
text.setBorderRadius( 6 );
c.setAlpha( 150 );
text.setBackgroundBrush( c );
return text;
}
};
然后就是使用的时候的简单的参考:
//初始化这个容器
plot = new QwtPlot(this);
plot->setTitle( "标题" );
//背景画布初始化(东西都是显示在这个画布上面)
canvas = new QwtPlotCanvas(plot);
//QFrame 边缘的效果
canvas->setLineWidth(2);
canvas->setMidLineWidth(2);
canvas->setFrameStyle(QFrame::Raised|QFrame::Box);
qDebug()<lineWidth()<midLineWidth()
<frameStyle();
canvas->setBorderRadius( 5 );
plot->setCanvas( canvas );
plot->setCanvasBackground( Qt::white );
//这里就是图例的样式,采用默认的,并在下方显示
plot->insertLegend( new QwtLegend(this),QwtPlot::BottomLegend );
// plot->axisTitle(QwtPlot::xBottom)
//默认的坐标轴
plot->setAxisTitle(QwtPlot::xBottom,"回合");
//消除横坐标回合的小刻度
plot->axisScaleDraw(QwtPlot::xBottom)->setTickLength(QwtScaleDiv::MajorTick,4);
plot->axisScaleDraw(QwtPlot::xBottom)->setTickLength(QwtScaleDiv::MediumTick,0);
plot->axisScaleDraw(QwtPlot::xBottom)->setTickLength(QwtScaleDiv::MinorTick,0);
// (plot->axisScaleDiv(QwtPlot::xBottom)).setInterval(0,1);
plot->setAxisTitle(QwtPlot::yLeft,"伤害");
//纵坐标的话就是小刻度短一点
plot->axisScaleDraw(QwtPlot::yLeft)->setTickLength(QwtScaleDiv::MajorTick,4);
plot->axisScaleDraw(QwtPlot::yLeft)->setTickLength(QwtScaleDiv::MinorTick,2);
//数据网格中的横线
grid = new QwtPlotGrid();
grid->enableX(false);
grid->enableXMin(false);
grid->setPen(Qt::darkGray,1);
grid->attach( plot );
//数据曲线
curveFriend = new QwtPlotCurve();
curveFriend->setTitle( "曲线1的标题" );
//线的样式
curveFriend->setPen( Qt::blue, 2 );
QColor c(Qt::blue);
c.setAlpha( 80 );
//填充内容的样式
curveFriend->setBrush(c);
//反锯齿
curveFriend->setRenderHint( QwtPlotItem::RenderAntialiased, true );
symbolF = new QwtSymbol( QwtSymbol::Ellipse,
QBrush( Qt::blue ), QPen( Qt::blue, 2 ), QSize( 4, 4 ) );
curveFriend->setSymbol( symbolF );
curveFriend->attach( plot );
curveEnemy = new QwtPlotCurve();
curveEnemy->setTitle( "曲线2的标题");
curveEnemy->setPen( Qt::red,2);
QColor r(Qt::red);
r.setAlpha( 80 );
curveEnemy->setBrush(r);
curveEnemy->setRenderHint( QwtPlotItem::RenderAntialiased, true );
//数据曲线上的点的样式。
symbolE = new QwtSymbol( QwtSymbol::Ellipse,
QBrush( Qt::red ), QPen( Qt::red, 2 ), QSize( 4, 4 ) );
curveEnemy->setSymbol( symbolE );
curveEnemy->attach( plot );
//鼠标显示,继承的一个自定义的类,实现鼠标的移动时显示的数据
MyPicker* myPicker = new MyPicker(plot->canvas());
//显示
plot->show();
// plot->setContentsMargins(10,10,10,10);
plot->plotLayout()->setCanvasMargin(0);
ui->gridLayout_main->addWidget(plot);
然后初始化之后可以动态的对统计图里面的数据进行修改跟新,比如弄个函数来进行:
void xx::setCurveData(QPolygonF pointsF ,QPolygonF pointsE,int N)
{
//数据的输入
curveFriend->setSamples( pointsF );
curveEnemy->setSamples( pointsE );
int canW = plot->canvas()->width();
//根据传入的坐标数值来决定坐标的刻度间隔
QFontMetrics bottomFontM = QFontMetrics(plot->axisFont(QwtPlot::xBottom));
int TickNum = canW/bottomFontM.width("111");//计算可以显示多少个坐标值(这里假定是3位数最多)
plot->setAxisScale( QwtPlot::xBottom, 1, N,N/TickNum );
//最后需要刷新一下
plot->replot();
}
这样就是大概的使用了,其实官方的文档比较的清晰了,结合他源码里的程序例子,都能实现我们需要的功能的。