PDA

View Full Version : drawing seperate custom QwtColumnSymbol for bar and legend icon



kangjoni
22nd May 2015, 12:25
I want to draw seperate custom symbol bar with some text number value inside the bar, but the legend icon seems following the same custom symbol bar representation.
I want that the text number is hidden in the legendlabel icon bar. And only showing on the center bar. here is my code so far based on the modification of barchat from the
example provided.
barchat.h


#ifndef _BAR_CHART_H_

#include <qwt_plot.h>

class QwtPlotMultiBarChart;

class BarChart: public QwtPlot
{
Q_OBJECT

public:
BarChart( QWidget * = NULL );

public Q_SLOTS:
void setMode( int );
void setOrientation( int );
void exportChart();

private:
void populate();
void fixlegend();
QVariantList mcolor;
QwtPlotMultiBarChart *d_barChartItem;
};

#endif



and barchat.cpp


#include "barchart.h"
#include <qwt_plot_renderer.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_multi_barchart.h>
#include <qwt_column_symbol.h>
#include <qwt_plot_layout.h>
#include <qwt_painter.h>
#include <qwt_legend.h>
#include <qwt_scale_draw.h>
#include <qwt_legend_label.h>

class ColumnSymbolBox:public QwtColumnSymbol
{
public:
ColumnSymbolBox():QwtColumnSymbol(QwtColumnSymbol: :Box),num(0){}
virtual void draw ( QPainter * painter,
const QwtColumnRect & rect ) const
{

QRectF r = rect.toRect();
if ( QwtPainter::roundingAlignment( painter ) )
{
r.setLeft( qRound( r.left() ) );
r.setRight( qRound( r.right() ) );
r.setTop( qRound( r.top() ) );
r.setBottom( qRound( r.bottom() ) );
}
qwtDrawPanel(painter,r,palette(),lineWidth());
painter->drawText(r, Qt::AlignTop| Qt::AlignHCenter,QString::number(num));


}
static void qwtDrawPanel( QPainter *painter, const QRectF &rect,
const QPalette &pal, double lw )
{
if ( lw > 0.0 )
{
if ( rect.width() == 0.0 )
{
painter->setPen( pal.window().color() );
painter->drawLine( rect.topLeft(), rect.bottomLeft() );
return;
}

if ( rect.height() == 0.0 )
{
painter->setPen( pal.window().color() );
painter->drawLine( rect.topLeft(), rect.topRight() );
return;
}

lw = qMin( lw, rect.height() / 2.0 - 1.0 );
lw = qMin( lw, rect.width() / 2.0 - 1.0 );

const QRectF outerRect = rect.adjusted( 0, 0, 1, 1 );
const QRectF innerRect = outerRect.adjusted( lw, lw, -lw, -lw );

QPolygonF lines[2];

lines[0] += outerRect.bottomLeft();
lines[0] += outerRect.topLeft();
lines[0] += outerRect.topRight();
lines[0] += innerRect.topRight();
lines[0] += innerRect.topLeft();
lines[0] += innerRect.bottomLeft();

lines[1] += outerRect.topRight();
lines[1] += outerRect.bottomRight();
lines[1] += outerRect.bottomLeft();
lines[1] += innerRect.bottomLeft();
lines[1] += innerRect.bottomRight();
lines[1] += innerRect.topRight();

painter->setPen( Qt::NoPen );

painter->setBrush( pal.light() );
painter->drawPolygon( lines[0] );
painter->setBrush( pal.dark() );
painter->drawPolygon( lines[1] );
//painter->save();
}

painter->drawRect( rect.adjusted( lw, lw, -lw + 1, -lw + 1 ));
painter->setBrush(pal.window() );
painter->setPen(Qt::white);
}
double num;
};

BarChart::BarChart( QWidget *parent ):
QwtPlot( parent )
{
setAutoFillBackground( true );

setPalette( Qt::white );
canvas()->setPalette( QColor( "LemonChiffon" ) );

setTitle( "Bar Chart" );

setAxisTitle( QwtPlot::yLeft, "Whatever" );
setAxisTitle( QwtPlot::xBottom, "Whatever" );

d_barChartItem = new QwtPlotMultiBarChart( "Bar Chart " );
d_barChartItem->setLayoutPolicy( QwtPlotMultiBarChart::AutoAdjustSamples );
d_barChartItem->setSpacing( 20 );
d_barChartItem->setMargin( 3 );

d_barChartItem->attach( this );
QwtLegend *legend = new QwtLegend();
legend->setDefaultItemMode( QwtLegendData::Clickable );
insertLegend( legend );

populate();
setOrientation( 0 );

setAutoReplot( true );
}

void BarChart::populate()
{
mcolor << QColor(Qt::darkRed) << QColor(Qt::darkGreen)<<QColor(Qt::darkCyan) <<QColor(Qt::darkYellow);

const int numSamples = 5;
QList<QwtText> titles;
for ( int i = 0; i < mcolor.size(); i++ )
{
QString title("Bar %1");
titles += title.arg( i );
}
d_barChartItem->setBarTitles( titles );
d_barChartItem->setLegendIconSize( QSize( 10, 14 ) );
QVector<double> values;
for ( int j = 0; j < mcolor.size(); j++ ) values += ( 2 + qrand() % 8 );

for ( int i = 0; i < mcolor.size(); i++ )
{
ColumnSymbolBox *symbol = new ColumnSymbolBox();
symbol->setLineWidth( 2 );
symbol->setPalette( QPalette( mcolor[i].value<QColor>() ) );
symbol->num=values.at(i);
d_barChartItem->setSymbol( i, symbol );
}

QVector< QVector<double> > series;
for ( int i = 0; i < numSamples; i++ )
{

series += values;
}
fixlegend();
d_barChartItem->setSamples( series );
}
void BarChart::fixlegend()
{
auto m = d_barChartItem->plot()->legend()->findChildren<QwtLegendLabel*>();
if (!m.isEmpty()){
//
qDebug() << "m.size() == mcolor.size()"<<m.size()<<":"<<mcolor.size();
if (m.size() !=mcolor.size()) {
qDebug() << "m.size() == mcolor.size()"<<m.size()<<":"<<mcolor.size()<<"failed";
return;
}
for (int x=0;x<m.size();x++){
QImage pic;
pic.fill(mcolor.at(x).value<QColor>());
QPixmap pmap,mpmap;
pmap.convertFromImage(pic);
// m[x]->setIcon(pmap); //here problematic QPixmap, I dont understand why this was null
// the text symbol from the center bar was also being drawn here, so how to remove the text symbol and draw only intended color one based on the center bar?
}
}
}
void BarChart::setMode( int mode )
{
if ( mode == 0 )
{
d_barChartItem->setStyle( QwtPlotMultiBarChart::Grouped );
}
else
{
d_barChartItem->setStyle( QwtPlotMultiBarChart::Stacked );
}
fixlegend();
}

void BarChart::setOrientation( int orientation )
{
QwtPlot::Axis axis1, axis2;

if ( orientation == 0 )
{
axis1 = QwtPlot::xBottom;
axis2 = QwtPlot::yLeft;

d_barChartItem->setOrientation( Qt::Vertical );
}
else
{
axis1 = QwtPlot::yLeft;
axis2 = QwtPlot::xBottom;

d_barChartItem->setOrientation( Qt::Horizontal );
}

setAxisScale( axis1, 0, d_barChartItem->dataSize() - 1, 1.0 );
setAxisAutoScale( axis2 );

QwtScaleDraw *scaleDraw1 = axisScaleDraw( axis1 );
scaleDraw1->enableComponent( QwtScaleDraw::Backbone, false );
scaleDraw1->enableComponent( QwtScaleDraw::Ticks, false );

QwtScaleDraw *scaleDraw2 = axisScaleDraw( axis2 );
scaleDraw2->enableComponent( QwtScaleDraw::Backbone, true );
scaleDraw2->enableComponent( QwtScaleDraw::Ticks, true );

plotLayout()->setAlignCanvasToScale( axis1, true );
plotLayout()->setAlignCanvasToScale( axis2, false );

plotLayout()->setCanvasMargin( 0 );
updateCanvasMargins();
fixlegend();
replot();
}

void BarChart::exportChart()
{
QwtPlotRenderer renderer;
renderer.exportTo( this, "barchart.pdf" );
}



So, what is your good way recommendation for fixlegend function in barchat.cpp . thanks

Uwe
26th May 2015, 07:34
I want to draw seperate custom symbol bar with some text number value inside the bar, but the legend icon seems following the same custom symbol bar representation.
I want that the text number is hidden in the legendlabel icon bar.
Overload QwtPlotMultiBarChart::legendIcon(), drawing your customized bar without the text.

Uwe