PDA

View Full Version : Custom symbol for QwtPlotMarker



pkj
23rd February 2011, 08:11
1. Subclass QwtSymbol

class Symbol:public QwtSymbol
{
public:
Symbol(const QBrush &, const QPen &, const QSize & ): QwtSymbol(QwtSymbol::NoSymbol, br, p, sz)
void drawSymbol( QPainter *, const QPointF & ) const
{
painter->setBrush( brush() );
painter->setPen( pen() );

const QSize sz = size();
const int sw = sz.width();
const int sh = sz.height();
const int sw2 = sz.width() / 2;
const int sh2 = sz.height() / 2;


QPainterPath path;
path.moveTo(pos);
path.lineTo(pos.x()-sw2,pos.y()); path.lineTo(pos.x(),pos.y()+sh2); path.lineTo(pos);
painter->drawPath(path);
}
};

2.Subclass QwtPlotMarker

class Marker:public QwtPlotMarker
{
public:
Marker():QwtPlotMarker(){}
void drawAt( QPainter *, const QRectF &, const QPointF & ) const
{
symbol().drawSymbol(painter, pos);
QwtPlotMarker::drawAt(painter, rect, pos);
}
};

3. instantiate and use
........

Marker *mrk = new Marker();
mrk->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
mrk->setLineStyle(QwtPlotMarker::HLine);
mrk->setSymbol(new Symbol(QColor(Qt::yellow), QColor(Qt::green), QSize(15,15)));
mrk->setValue(10.0,10.0);
............

Problem I face:while the marker is displayed fine, symbol is not drawn...

Uwe
23rd February 2011, 08:38
You forgot to implement Symbol::clone().

Uwe

pkj
23rd February 2011, 08:58
sorry for being such a newbie... but qwt_symbol.h doesn't have any clone()
What and how should i implement clone()...
Thanks for your time, Uwe:)

Uwe
23rd February 2011, 09:29
Ah sorry you are on Qwt 6 - the right answer here is: you can overload virtual methods only.

This one is what you are looking for:


virtual void drawSymbols( QPainter *,
const QPointF *, int numPoints ) const;Uwe

pkj
23rd February 2011, 11:40
Thanks Uwe, works like a charm :).
Anyone interested here's a trivial example:
Step 1 : subclass QwtSymbol

class Symbol:public QwtSymbol
{
public:
Symbol(const QBrush &, const QPen &, const QSize & );
virtual void drawSymbols( QPainter *, const QPointF *, int numPoints ) const;
void drawSymbol( QPainter *, const QPointF & ) const;
};

Symbol::Symbol(const QBrush &br , const QPen &p, const QSize &sz)
: QwtSymbol(QwtSymbol::NoSymbol, br, p, sz)
{
}

void Symbol::drawSymbol(QPainter *painter, const QPointF &pos) const
{
drawSymbols( painter, &pos, 1 );
}

void Symbol::drawSymbols(QPainter *painter, const QPointF *points, int numPoints) const
{
if ( numPoints <= 0 )
return;

painter->save();
painter->setBrush( brush() );
painter->setPen( pen() );
const QSize sz = size();
const int sw = sz.width();
const int sh = sz.height();
const int sw2 = sz.width() / 2;
const int sh2 = sz.height() / 2;
QPointF pos = points[0];

QPainterPath path;
path.moveTo(pos);
path.lineTo(pos.x()-sw2,pos.y()); path.lineTo(pos.x(),pos.y()+sh2); path.lineTo(pos);
painter->drawPath(path);
painter->restore();
}


Step 2: Subclass QwtMarker


class Marker:public QwtPlotMarker
{
public:
Marker();
void drawAt( QPainter *, const QRectF &, const QPointF & ) const;
virtual void draw( QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF & ) const;
};

Marker::Marker() :QwtPlotMarker()
{}

void Marker::drawAt(QPainter *painter, const QRectF &rect, const QPointF &pos) const
{
symbol().drawSymbol(painter, pos);
QwtPlotMarker::drawAt(painter, rect, pos);
}
void Marker::draw( QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap,
const QRectF &canvasRect ) const
{
const double x = xMap.transform( xValue() );
const double y = yMap.transform( yValue() );

drawAt( painter, canvasRect, QPointF( x, y ) );
}

Step 3: Instantiate and use


...
...
Marker *mrk = new Marker();
mrk->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
mrk->setValue(10.0,10.0);
mrk->setLineStyle(QwtPlotMarker::HLine);
mrk->setSymbol(new Symbol(QColor(Qt::yellow), QColor(Qt::green), QSize(15,15)));
mrk->attach(qwt_plot_object);

sonulohani
24th May 2012, 10:28
It is showing error------->

error: 'drawAt' is not a member of 'QwtPlotMarker'

Spitfire
24th May 2012, 11:59
There isn't QwtPlotMarker::drawAt() there's Marker::drawAt().
If you're using pointers, you have to cast QwtPlotMarker to Marker to be able to use methods added in derived class.

sonulohani
29th May 2012, 11:34
Sir, could you please give a well defined example on drawSymbols() as i want to draw a symbol based on image .

sonulohani
30th May 2012, 05:47
this example is wrong since it is calling a virtual method i.e. drawSymbols().

ChrisW67
30th May 2012, 08:38
... and what is wrong with calling a virtual function? Nothing, and it has nothing to do with the error message you are getting either I guess.

How about you actually try to participate in solving your problem in future. Just saying "It doesn't work", or asking over and over and over for someone to give you a canned solution you can copy without thought, is often unproductive and unlikely to win you friends. Tells us what errors you are seeing, what you have tried to fix it etc. Ask a smart question. (http://www.catb.org/~esr/faqs/smart-questions.html#intro)

Just to see the end of this, a complete example with a custom pixmap as the symbol for both a marker and the data points:


#include <QApplication>
#include <QPainter>

#include <qwt_plot_curve.h>
#include <qwt_plot.h>
#include <qwt_plot_marker.h>
#include <qwt_symbol.h>

class Symbol:public QwtSymbol
{
public:
Symbol(const QPixmap &pixmap);
QSize boundingSize() const;
void drawSymbols( QPainter *, const QPointF *, int numPoints ) const;
private:
QPixmap m_pixmap;
};

Symbol::Symbol(const QPixmap &pixmap):
QwtSymbol(QwtSymbol::UserStyle),
m_pixmap(pixmap)
{
}

QSize Symbol::boundingSize() const
{
return m_pixmap.size();
}


void Symbol::drawSymbols(QPainter *painter, const QPointF *points, int numPoints) const
{
painter->save();
for(int i = 0; i < numPoints; ++i)
painter->drawPixmap(points[i], m_pixmap);
painter->restore();
}

int main (int argc, char **argv)
{
QApplication a(argc, argv);

const int Size = 30;
double xval[Size];
double yval[Size];
for(int i = 0; i < Size; ++i) {
xval[i] = double(i) * 10.0 / double(Size - 1);
yval[i] = qSin(xval[i]) * qCos(2.0 * xval[i]);
}

QwtPlot myPlot;
QwtPlotCurve curve("Curve");
curve.setRawSamples(xval, yval, Size);
QPixmap p1("p1.png");
curve.setSymbol(new Symbol(p1));
curve.attach(&myPlot);

QwtPlotMarker mrk;
mrk.setLinePen(QPen(Qt::black, 0, Qt::DashDotLine));
mrk.setValue(0.5, 0.5);
mrk.setLineStyle(QwtPlotMarker::HLine);
QPixmap p2("p2.png");
mrk.setSymbol(new Symbol(p2));
mrk.attach(&myPlot);

myPlot.resize(640,480);
myPlot.show();

return a.exec();
}

Built and tested Qwt 6.0.1 on Linux. Make your own p1.png and p2.png markers.

sonulohani
1st June 2012, 08:48
Thank you ChrisW67, you're awesome.

Added after 1 34 minutes:

Sir,
I want to ask one last thing i.e.; whenever i am trying to write class code i.e.; symbol, in header file then it is giving error as first defined here pointing to constructor. Why is this happening????

sonulohani
1st June 2012, 10:08
I understood what is the problem. A very very thanks to you. Its working now. And sorry for querying again and again. I sometimes become insane. But atlast by your help, i figured out what was my mistake. May God bless you.

SeniorSpielbergo
3rd June 2012, 16:11
Hi,

I copied ChrisW67's example into my project and modified it just a little bit (renamed the Symbol class, made it use just a predefined static file and just added the marker). Now I have got the problem that there is no marker displayed. Even when I use a Symbol shipped with Qwt it is not displayed. Does anybody know what I might be doing wrong?

Any help is appreciated.
Thanks in advance.

David

Added after 5 minutes:

Sorry for bothering you guys.
I solved it myself.
Really stupid mistake. The image file was in the wrong place.