Branda
Branda

Reputation: 73

How to change the color of a QGraphicsRectItem

I want to change the color of a QGraphicsRectItem when a particular event occurs. The fact is that it seems that once the override paint method is called, the color won't change no matter what.

Simplified code of what I've done:

item.h:

class Item : public QGraphicsRectItem
{
public:
    Item(QGraphicsView *graphView);
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override;

private:
    QPointF newPos;
    QGraphicsView *graph;
};

item.cpp:

Item::Item(QGraphicsView *graphWidget) : graph(graphWidget) { }

void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
     painter->setPen(Qt::NoPen);
     painter->setBrush(Qt::black);
     painter->drawEllipse(-7, -7, 20, 20);
}

main.cpp:

int main(int argc, char *argv[])
{
     srand(QDateTime::currentDateTime().toMSecsSinceEpoch());
     QApplication a(argc, argv);
     QGraphicsScene scene;
     QGraphicsView view(&scene);

     Item *item = new Item(&view);
     scene.addItem(item);
     item->setPos(0, 0);

     item->setBrush(Qt::red);
     item->update();

     view.show();
     return a.exec();
}

Upvotes: 1

Views: 2278

Answers (1)

apalomer
apalomer

Reputation: 1935

If I understand properly your question, the problem is that after item->setBrush(Qt::red), your circle is not being painter red. If this is the case, the problem is that you are forcing a specific pen (Qt::NoPen) and brush (Qt::red) in your paint function, and you are not using Item::pen() and Item::brush() to retrieve the information. Instead, you can do the following:

Item::Item(QGraphicsView *graphWidget) : graph(graphWidget)
{
  setPen(Qt::NoPen);
  setBrush(Qt::black);
}

void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
  Q_UNUSED(option);
  painter->setPen(pen());
  painter->setBrush(brush());
  painter->drawEllipse(-7, -7, 20, 20);
}

This way, you define the default pen and brush in the constructor, but you can still change them using Item::setPen and Item::setBrush. Moreover, for this example you would be better inheriting QAbstractGraphicsShapeItem but then you have to implement Item::boundingRectfunction. The following example outputs a red circle (which is what I suspect you want to do) and also draw the contour with black (although it is not what you wanted, but to show that pen also changes):

#include <QApplication>
#include <QDateTime>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsView>

class Item : public QAbstractGraphicsShapeItem
{
public:
  Item(QGraphicsView *graphView);

  void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) override;

  virtual QRectF boundingRect() const override;

private:
  QPointF newPos;
  QGraphicsView *graph;
};

Item::Item(QGraphicsView *graphWidget) : graph(graphWidget)
{
  setPen(Qt::NoPen);
  setBrush(Qt::black);
}

void Item::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{
  Q_UNUSED(option);
  painter->setPen(pen());
  painter->setBrush(brush());
  painter->drawEllipse(-7, -7, 20, 20);
}

QRectF Item::boundingRect() const
{
  double pw = pen().widthF() / 2;
  return QRectF(QPointF(-7 - pw, -7 - pw), QSizeF(20 + 2 * pw, 20 + 2 * pw));
}

int main(int argc, char *argv[])
{
  srand(QDateTime::currentDateTime().toMSecsSinceEpoch());
  QApplication a(argc, argv);
  QGraphicsScene scene;
  QGraphicsView view(&scene);

  Item *item = new Item(&view);
  scene.addItem(item);
  item->setPos(0, 0);

  item->setBrush(Qt::red);
  item->setPen(QPen(Qt::black));
  item->update();

  view.show();
  return a.exec();
}

Upvotes: 2

Related Questions