Search code examples
qtqt5qgraphicsitem

QGraphicsPathItem: paint elements differently


How do I paint a QGraphicsPathItem in a way that it will fade out after n-elements at the end?

Every second I add a QPointF to the end of the path and wish to display the n-th element with 100% opacity. And n-1 with 90%, n-2 with 80% etc. So the path only show the last 10 (for example) and smoothly fades out. But how can I do that with qt5?

I figured how to change color of the entire path, but how do I change it on sub-item level... meaning here the path elements?


Solution

  • I would use separate QGraphicsLineItem for each segment and adjust their opacity independently:

    class Object : public QObject {
      Q_OBJECT
    public:
      Object();
      void add_point(QPointF point);
    private:
      QGraphicsScene m_scene;
      QList<QGraphicsLineItem*> m_items;
      QPointF m_previous_point;
    private slots:
      void timeout();
    };
    
    Object::Object() {
      QGraphicsView* view = new QGraphicsView();
      view->setRenderHint(QPainter::Antialiasing);
      view->setScene(&m_scene);
      view->scale(10, 10);
      view->resize(400, 200);
      view->show();
      QTimer* timer = new QTimer(this);
      timer->start(30);
      connect(timer, &QTimer::timeout, this, &Object::timeout);
    }
    
    void Object::add_point(QPointF point) {
      const int MAX_SEGMENTS = 100;
      QGraphicsLineItem* new_line = 
          m_scene.addLine(QLineF(m_previous_point, point));
      QPen pen;
      pen.setCosmetic(true);
      pen.setWidth(3);
      new_line->setPen(pen);
      m_items.append(new_line);
      while(m_items.count() > MAX_SEGMENTS) {
        delete m_items[0];
        m_items.removeFirst();
      }
      for(int i = 0; i < m_items.count(); i++) {
        m_items[i]->setOpacity(
            1.0 - 1.0 / MAX_SEGMENTS * (m_items.count() - 1 - i));
      }
      m_previous_point = point;
    }
    
    void Object::timeout() {
      double x = m_previous_point.x() + 0.1;
      add_point(QPointF(x, qSin(x)));
    }