Reputation: 886
I originally implement my graph by drawing all the content in the QWidget::paintEvent()
. I have a function drawHeatMapLegend()
to draw a box with QLinearGradient to represent a heat-map for my graph as legend.
Original implementation
widMapGraph::widMapGraph(QWidget parent = 0) : QWidget(parent) {
gradient_.setCoordinateMode(QGradient::ObjectBoundingMode);
gradient_.setColorAt(0.0, Qt::green);
gradient_.setColorAt(0.3, Qt::yellow);
gradient_.setColorAt(0.6, Qt::red);
}
void widMapGraph::paintEvent(QPaintEvent *event) {
QPainter painter(this);
drawHeatMapLegend(&painter);
}
void widMapGraph::drawHeatMapLegend(QPainter* painter) {
QRect legendBox(30, 70, 25, 100);
int left = legendBox.left() + legendBox.width() + 10;
painter->save();
painter->setPen(QPen());
painter->setBrush(gradient_);
painter->drawRect(legendBox);
painter->drawText(left, legendBox.top(), "0.00%");
painter->drawText(left, legendBox.top() + legendBox.height() / 2, "50.00%");
painter->drawText(left, legendBox.top() + legendBox.height(), "100.00%");
painter->restore();
} // end: (widMapGraph::drawHeatMapLegend)
Now, I try to use QGraphicScene/QGraphicsView framework for my graph and I implement a subclass of QGraphicsRectItem for my map legend.
Class definition
class MapLegend : public QObject, public QGraphicsRectItem {
Q_OBJECT
public:
MapLegend(QGraphicsItem *parent = 0);
void paint (QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget);
QLinearGradient gradient_;
/* other members */
}
Class implementation
MapLegend::MapLegend(QGraphicsItem *parent) : QGraphicsRectItem(parent) {
setRect(30, 70, 25, 100);
gradient_.setCoordinateMode(QGradient::ObjectBoundingMode);
gradient_.setColorAt(0.0, Qt::green);
gradient_.setColorAt(0.3, Qt::yellow);
gradient_.setColorAt(0.6, Qt::red);
} // end_ctor(MapLegend)
void MapLegend::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
Q_UNUSED(option);
Q_UNUSED(widget);
int left = rect().left() + rect().width() + 10;
painter->setPen(QPen());
painter->setBrush(gradient_);
painter->drawRect(rect());
painter->drawText(left, rect().top(), "0.00%");
painter->drawText(left, rect().top() + rect().height() / 2, "50.00%");
painter->drawText(left, rect().top() + rect().height(), "100.00%");
} // end: MapLegend::paint()
void My2ndGraph::task() {
myView->scene()->clear();
myView->scene()->addItem(myLegend); // myLegend is a class variable as MapLegend
update();
}
Result The orange box shows two examples using 2nd implementation
Question The original implementation correctly show a gradient 'vertically' along the box, but the new implementation draw the gradient diagonally. Is there anything I missed that why the two implementations behavior dis-agree? Thanks
Upvotes: 2
Views: 3441
Reputation: 22346
You haven't set the start and stop end points of the gradient, so it defaults to using the top left and bottom right corners:
QLinearGradient::QLinearGradient() Constructs a default linear gradient with interpolation area between (0, 0) and (1, 1).
and:
QGradient::ObjectBoundingMode: In this mode the gradient coordinates are relative to the bounding rectangle of the object being drawn, with (0,0) in the top left corner, and (1,1) in the bottom right corner of the object's bounding rectangle.
So you will need to manually tell it the gradient direction, like this:
gradient_.setStart( 0.0, 0.0 );
gradient_.setFinalStop( 0.0, 1.0 );
Or when initialised:
MapLegend::MapLegend(QGraphicsItem *parent) : QGraphicsRectItem(parent),
gradient_( QLinearGradient( 0.0, 0.0, 0.0, 1.0 ) ) { ... }
As for why it worked inside a QWidget
? I have no idea, it shouldn't have!
Upvotes: 2