Hallo Uwe
danke für den Tipp. Daran hatte ich auch schon gedacht, habe an der stelle allerdings nicht genau gewusst wie ich es mit dem privaten Member d_data umgehen soll. Habe jetzt folgendes Ausgearbeitet:
Code: Alles auswählen
#ifndef MYMARKER_H
#define MYMARKER_H
#include "qwt_plot_marker.h"
class MyMarker:public QwtPlotMarker
{
public:
MyMarker();
virtual void drawLabel( QPainter *painter, const QRectF & canvasRect, const QPointF &pos ) const;
void setAngle(double );
private:
class MyPrivateData;
MyPrivateData *d_data;
double angle;
};
#endif // MYMARKER_H
Code: Alles auswählen
#include "mymarker.h"
#include "qwt_symbol.h"
MyMarker::MyMarker()
{
angle=0.0;
}
class MyMarker::MyPrivateData
{
public:
MyPrivateData():
labelAlignment( Qt::AlignCenter ),
labelOrientation( Qt::Horizontal ),
spacing( 2 ),
symbol( NULL ),
style( QwtPlotMarker::NoLine ),
xValue( 0.0 ),
yValue( 0.0 )
{
}
~MyPrivateData()
{
delete symbol;
}
QwtText label;
Qt::Alignment labelAlignment;
Qt::Orientation labelOrientation;
int spacing;
QPen pen;
const QwtSymbol *symbol;
LineStyle style;
double xValue;
double yValue;
};
void MyMarker::drawLabel( QPainter *painter, const QRectF & canvasRect, const QPointF &pos ) const
{
MyPrivateData * myData=new MyPrivateData;
myData->label=label();
myData->labelAlignment=labelAlignment();
myData->labelOrientation=labelOrientation();
myData->spacing=spacing();
myData->pen=linePen();
myData->symbol=symbol();
myData->style=lineStyle();
myData->xValue=xValue();
myData->yValue=yValue();
if ( myData->label.isEmpty() )
return;
Qt::Alignment align = myData->labelAlignment;
QPointF alignPos = pos;
QSizeF symbolOff( 0, 0 );
switch ( myData->style )
{
case QwtPlotMarker::VLine:
{
// In VLine-style the y-position is pointless and
// the alignment flags are relative to the canvas
if ( myData->labelAlignment & Qt::AlignTop )
{
alignPos.setY( canvasRect.top() );
align &= ~Qt::AlignTop;
align |= Qt::AlignBottom;
}
else if ( myData->labelAlignment & Qt::AlignBottom )
{
// In HLine-style the x-position is pointless and
// the alignment flags are relative to the canvas
alignPos.setY( canvasRect.bottom() - 1 );
align &= ~Qt::AlignBottom;
align |= Qt::AlignTop;
}
else
{
alignPos.setY( canvasRect.center().y() );
}
break;
}
case QwtPlotMarker::HLine:
{
if ( myData->labelAlignment & Qt::AlignLeft )
{
alignPos.setX( canvasRect.left() );
align &= ~Qt::AlignLeft;
align |= Qt::AlignRight;
}
else if ( myData->labelAlignment & Qt::AlignRight )
{
alignPos.setX( canvasRect.right() - 1 );
align &= ~Qt::AlignRight;
align |= Qt::AlignLeft;
}
else
{
alignPos.setX( canvasRect.center().x() );
}
break;
}
default:
{
if ( myData->symbol &&
( myData->symbol->style() != QwtSymbol::NoSymbol ) )
{
symbolOff = myData->symbol->size() + QSizeF( 1, 1 );
symbolOff /= 2;
}
}
}
qreal pw2 = myData->pen.widthF() / 2.0;
if ( pw2 == 0.0 )
pw2 = 0.5;
const int spacing = myData->spacing;
const qreal xOff = qMax( pw2, symbolOff.width() );
const qreal yOff = qMax( pw2, symbolOff.height() );
const QSizeF textSize = myData->label.textSize( painter->font() );
if ( align & Qt::AlignLeft )
{
alignPos.rx() -= xOff + spacing;
if ( myData->labelOrientation == Qt::Vertical )
alignPos.rx() -= textSize.height();
else
alignPos.rx() -= textSize.width();
}
else if ( align & Qt::AlignRight )
{
alignPos.rx() += xOff + spacing;
}
else
{
if ( myData->labelOrientation == Qt::Vertical )
alignPos.rx() -= textSize.height() / 2;
else
alignPos.rx() -= textSize.width() / 2;
}
if ( align & Qt::AlignTop )
{
alignPos.ry() -= yOff + spacing;
if ( myData->labelOrientation != Qt::Vertical )
alignPos.ry() -= textSize.height();
}
else if ( align & Qt::AlignBottom )
{
alignPos.ry() += yOff + spacing;
if ( myData->labelOrientation == Qt::Vertical )
alignPos.ry() += textSize.width();
}
else
{
if ( myData->labelOrientation == Qt::Vertical )
alignPos.ry() += textSize.width() / 2;
else
alignPos.ry() -= textSize.height() / 2;
}
painter->translate( alignPos.x(), alignPos.y() );
if ( myData->labelOrientation == Qt::Vertical )
painter->rotate( -90.0 );
painter->rotate( angle );
const QRectF textRect( 0, 0, textSize.width(), textSize.height() );
myData->label.draw( painter, textRect );
}
void MyMarker::setAngle(double newAngle){
angle=newAngle;
}
und zum Schluss das ganze als Beipsiel in simpleplot aus den QWT-Examples getestet
Code: Alles auswählen
#include <qapplication.h>
#include <qlayout.h>
#include <qwt_plot.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_legend.h>
#include <qwt_point_data.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_text.h>
#include <qwt_symbol.h>
#include <qwt_math.h>
#include <math.h>
#include "mymarker.h"
//-----------------------------------------------------------------
// simple.cpp
//
// A simple example which shows how to use QwtPlot connected
// to a data class without any storage, calculating each values
// on the fly.
//-----------------------------------------------------------------
class FunctionData: public QwtSyntheticPointData
{
public:
FunctionData( double( *y )( double ) ):
QwtSyntheticPointData( 100 ),
d_y( y )
{
}
virtual double y( double x ) const
{
return d_y( x );
}
private:
double( *d_y )( double );
};
class ArrowSymbol: public QwtSymbol
{
public:
ArrowSymbol()
{
QPen pen( Qt::black, 0 );
pen.setJoinStyle( Qt::MiterJoin );
setPen( pen );
setBrush( Qt::red );
QPainterPath path;
path.moveTo( 0, 8 );
path.lineTo( 0, 5 );
path.lineTo( -3, 5 );
path.lineTo( 0, 0 );
path.lineTo( 3, 5 );
path.lineTo( 0, 5 );
QTransform transform;
transform.rotate( -30.0 );
path = transform.map( path );
setPath( path );
setPinPoint( QPointF( 0, 0 ) );
setSize( 10, 14 );
}
};
class Plot : public QwtPlot
{
public:
Plot( QWidget *parent = NULL );
protected:
virtual void resizeEvent( QResizeEvent * );
private:
void populate();
void updateGradient();
};
Plot::Plot( QWidget *parent ):
QwtPlot( parent )
{
setAutoFillBackground( true );
setPalette( QPalette( QColor( 165, 193, 228 ) ) );
updateGradient();
setTitle( "A Simple QwtPlot Demonstration" );
insertLegend( new QwtLegend(), QwtPlot::RightLegend );
// axes
setAxisTitle( xBottom, "x -->" );
setAxisScale( xBottom, 0.0, 10.0 );
setAxisTitle( yLeft, "y -->" );
setAxisScale( yLeft, -1.0, 1.0 );
// canvas
QwtPlotCanvas *canvas = new QwtPlotCanvas();
canvas->setLineWidth( 1 );
canvas->setFrameStyle( QFrame::Box | QFrame::Plain );
canvas->setBorderRadius( 0 );
QPalette canvasPalette( Qt::white );
canvasPalette.setColor( QPalette::Foreground, QColor( 133, 190, 232 ) );
canvas->setPalette( canvasPalette );
setCanvas( canvas );
// panning with the left mouse button
( void ) new QwtPlotPanner( canvas );
// zoom in/out with the wheel
( void ) new QwtPlotMagnifier( canvas );
populate();
}
void Plot::populate()
{
// Insert new curves
QwtPlotCurve *cSin = new QwtPlotCurve( "y = sin(x)" );
cSin->setRenderHint( QwtPlotItem::RenderAntialiased );
cSin->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
cSin->setPen( Qt::red );
cSin->attach( this );
QwtPlotCurve *cCos = new QwtPlotCurve( "y = cos(x)" );
cCos->setRenderHint( QwtPlotItem::RenderAntialiased );
cCos->setLegendAttribute( QwtPlotCurve::LegendShowLine, true );
cCos->setPen( Qt::blue );
cCos->attach( this );
// Create sin and cos data
cSin->setData( new FunctionData( ::sin ) );
cCos->setData( new FunctionData( ::cos ) );
// Insert markers
// ...a horizontal line at y = 0...
QwtPlotMarker *mY = new QwtPlotMarker();
mY->setLabel( QString::fromLatin1( "y = 0" ) );
mY->setLabelAlignment( Qt::AlignRight | Qt::AlignTop );
mY->setLineStyle( QwtPlotMarker::HLine );
mY->setYValue( 0.0 );
mY->attach( this );
// ...a vertical line at x = 2 * pi
QwtPlotMarker *mX = new QwtPlotMarker();
mX->setLabel( QString::fromLatin1( "x = 2 pi" ) );
mX->setLabelAlignment( Qt::AlignLeft | Qt::AlignBottom );
mX->setLabelOrientation( Qt::Vertical );
mX->setLineStyle( QwtPlotMarker::VLine );
mX->setLinePen( Qt::black, 0, Qt::DashDotLine );
mX->setXValue( 2.0 * M_PI );
mX->attach( this );
const double x = 7.7;
// an arrow at a specific position
MyMarker *mPos = new MyMarker;
mPos->setRenderHint( QwtPlotItem::RenderAntialiased, true );
mPos->setItemAttribute( QwtPlotItem::Legend, true );
mPos->setSymbol( new ArrowSymbol() );
mPos->setAngle(90);
mPos->setValue( QPointF( x, ::sin( x ) ) );
mPos->setLabel( QString( "x = %1" ).arg( x ) );
mPos->setLabelAlignment( Qt::AlignRight | Qt::AlignBottom );
mPos->attach( this );
}
void Plot::updateGradient()
{
QPalette pal = palette();
const QColor buttonColor = pal.color( QPalette::Button );
QLinearGradient gradient( rect().topLeft(), rect().bottomLeft() );
gradient.setColorAt( 0.0, Qt::white );
gradient.setColorAt( 0.7, buttonColor );
gradient.setColorAt( 1.0, buttonColor );
pal.setBrush( QPalette::Window, gradient );
setPalette( pal );
}
void Plot::resizeEvent( QResizeEvent *event )
{
QwtPlot::resizeEvent( event );
// Qt 4.7.1: QGradient::StretchToDeviceMode is buggy on X11
updateGradient();
}
int main( int argc, char **argv )
{
QApplication a( argc, argv );
Plot *plot = new Plot();
// We put a dummy widget around to have
// so that Qt paints a widget background
// when resizing
QWidget window;
QHBoxLayout *layout = new QHBoxLayout( &window );
layout->setContentsMargins( 0, 0, 0, 0 );
layout->addWidget( plot );
window.resize( 600, 400 );
window.show();
return a.exec();
}
in der Funktion populate() ist ein neues Objekt der Klasse myMarker und die Funktion setAngle() zu finden.
Hast du es in etwa so gemeint? Mich würde deine Meinung dazu interessieren.
Gora