QwtPolar 是Qt的一个第三方扩展控件,提供了极坐标下函数图形绘制的功能。我上一篇博客介绍了如何安装QwtPolar ,这次就写写如何使用QwtPolar 。
如果只是简单的用QwtPolar 显示个极坐标下的图形,只要会使用下面三个类就可以了。
QwtPolarPlot A plotting widget, displaying a polar coordinate system
QwtPolarGrid An item which draws scales and grid lines on a polar plot
QwtPolarCurve An item, that represents a series of points
QwtPolarPlot
是绘图控件,最终的图形都绘制在它上面。下面是个最简单的代码:
#include <QApplication>
#include <qwt_polar_plot.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QwtPolarPlot plot;
plot.resize( 600, 600 );
plot.show();
return app.exec();
}
编译运行之后的效果如下。可以看到窗口中白色区域就是QwtPolarPlot 控件的绘制区域。
QwtPolarPlot 有一些基本的接口,比如setPlotBackground (const QBrush &c)、setTitle (const QString &)、setAutoScale (int scaleId)、setScale (int scaleId, double min, double max, double step=0)、insertLegend (QwtAbstractLegend *, LegendPosition=RightLegend, double ratio=-1.0) 等。
下面将上面的代码扩展一点。
#include <QApplication>
#include <QTextCodec>
#include <qwt_polar_plot.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QwtPolarPlot plot;
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
plot.setTitle(QObject::tr("这是一个简单的例子"));
plot.setPlotBackground (QBrush( Qt::red, Qt::SolidPattern ));
plot.setScale( QwtPolar::ScaleAzimuth, 0, 360, 30);
plot.setScale( QwtPolar::ScaleRadius, 0, 10, 5);
plot.resize( 600, 600 );
plot.show();
return app.exec();
}
显示结果如下:
其中有两行代码的效果是看不到的:
plot.setScale( QwtPolar::ScaleAzimuth, 0, 360, 30);
plot.setScale( QwtPolar::ScaleRadius, 0, 10, 5);
如果我们在极坐标区域添加了网格,就能看出上面代码的作用了。
QwtPolar将网格相关的功能收归到QwtPolarGrid 类。
下面是扩展后的代码,增加了网格。
#include <QApplication>
#include <QTextCodec>
#include <qwt_polar_plot.h>
#include <qwt_polar_grid.h>
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QwtPolarPlot plot;
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
plot.setTitle(QObject::tr("这是一个简单的例子"));
plot.setPlotBackground (QBrush( Qt::red, Qt::SolidPattern ));
plot.setScale( QwtPolar::ScaleAzimuth, 0, 360, 30);
plot.setScale( QwtPolar::ScaleRadius, 0, 10, 5);
QwtPolarGrid grid;
grid.setFont (QFont("Times", 16, QFont::Bold));
grid.setPen ( QPen(Qt::blue, 1, Qt::DashDotLine) );
grid.setAxisPen ( QwtPolar::AxisAzimuth, QPen(Qt::black, 1) );
//grid.setAxisPen ( QwtPolar::AxisLeft, QPen(Qt::black, 1) );
grid.showGrid (QwtPolar::AxisAzimuth, true);
grid.showGrid (QwtPolar::AxisLeft, true);
grid.showGrid (QwtPolar::AxisRight, false);
grid.showGrid (QwtPolar::AxisTop, false);
grid.showGrid (QwtPolar::AxisBottom, false);
grid.attach(&plot);
plot.resize( 600, 600 );
plot.show();
return app.exec();
}
最后是最重要的,绘制具体的函数图形了。QwtPolarCurve 用来绘制曲线图,QwtPolarSpectrogram 用来绘制颜色映射的三位等高图。这里只简单的介绍QwtPolarCurve ,QwtPolarSpectrogram 的用法类似。
QwtPolarCurve 有个成员函数setData (QwtSeriesData< QwtPointPolar > *data),用它就可以将待绘图的数据传进来。传进来的data 是个QwtSeriesData< QwtPointPolar >型的指针。
QwtSeriesData< QwtPointPolar >类是个纯虚类,它只提供了接口,却没有具体实现这些接口。
因此我们需要将数据封装成QwtSeriesData< QwtPointPolar > 型的派生类,在派生类中将接口函数具体实现。
我们在这里画一个简单的心形线。心形线的参数方程最初由 de Castillon 在1741年的《Philosophical Transactions of the Royal Society》发表的;意为“像心脏的”。 极坐标系下的参数方程可以写为:r=a(1-cosθ),我们这里设定 a= 2.
查看QwtSeriesData< QwtPointPolar >的定义可知,QwtSeriesData< QwtPointPolar >中有三个纯虚函数需要我们来实现。
virtual size_t size () const =0
virtual QwtPointPolar sample (size_t i) const =0
virtual QRectF boundingRect () const =0
这里我定义了一个新的类MyData,代码如下:
class MyData: public QwtSeriesData< QwtPointPolar >
{
virtual size_t size() const
{
return 360;
}
virtual QwtPointPolar sample(size_t i) const
{
double theta;
double r;
theta = i / 180.0 * M_PI;
r = 2.0 * (1 - cos(theta));
return QwtPointPolar(i, r);
}
virtual QRectF boundingRect() const
{
//return qwtBoundingRect();
return QRectF(-2.0, -2.0, 4, 4);
}
};
有了这个代码后就可以实现全部的程序了。最后完整的代码如下:
#include <QApplication>
#include <QTextCodec>
#include <qwt_polar_plot.h>
#include <qwt_polar_grid.h>
#include <qwt_polar_curve.h>
#include <qwt_series_data.h>
class MyData: public QwtSeriesData< QwtPointPolar >
{
virtual size_t size() const
{
return 360;
}
virtual QwtPointPolar sample(size_t i) const
{
double theta;
double r;
theta = i / 180.0 * M_PI;
r = 2.0 * (1 - cos(theta));
return QwtPointPolar(i, r);
}
virtual QRectF boundingRect() const
{
//return qwtBoundingRect();
return QRectF(-2.0, -2.0, 4, 4);
}
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QwtPolarPlot plot;
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
plot.setTitle(QObject::tr("这是一个简单的例子"));
plot.setPlotBackground (QBrush( Qt::red, Qt::SolidPattern ));
plot.setScale( QwtPolar::ScaleAzimuth, 0, 360, 30);
plot.setScale( QwtPolar::ScaleRadius, 0, 4, 2);
QwtPolarGrid grid;
grid.setFont (QFont("Times", 12, QFont::Bold));
grid.setPen ( QPen(Qt::blue, 1, Qt::DashDotLine) );
//grid.setAxisFont (QwtPolar::AxisLeft, QFont("Times", 6));
grid.setAxisPen ( QwtPolar::AxisAzimuth, QPen(Qt::black, 1) );
//grid.setAxisPen ( QwtPolar::AxisLeft, QPen(Qt::black, 1) );
grid.showMinorGrid (QwtPolar::AxisLeft, false);
grid.showMinorGrid (QwtPolar::AxisRight, false);
grid.showMinorGrid (QwtPolar::AxisTop, false);
grid.showMinorGrid (QwtPolar::AxisBottom, false);
grid.showGrid (QwtPolar::AxisAzimuth, true);
grid.showGrid (QwtPolar::AxisLeft, true);
grid.showGrid (QwtPolar::AxisRight, false);
grid.showGrid (QwtPolar::AxisTop, false);
grid.showGrid (QwtPolar::AxisBottom, false);
grid.attach(&plot);
QwtPolarCurve curve;
curve.setPen (QPen(Qt::green, 3));
MyData data;
curve.setData (&data);
curve.attach(&plot);
plot.resize( 600, 600 );
plot.show();
return app.exec();
}
至此,QwtPolar 基本的用法就介绍完了。希望对大家有用。