[SOLVED] Painting gradients with QGraphicsItem



  • Hello everyone,
    I want to draw a QGraphicsItem and fill it with a QLinearGradient.
    I've subclassed the Item implemented the paint function for testig like this:

        painter->save();
    
        QLinearGradient gradient(m_BoxSize.topLeft(), m_BoxSize.bottomRight());
        gradient.setColorAt(0, Qt::green);
        gradient.setColorAt(1, Qt::red);
    
        painter->fillPath(shape(), gradient);
        painter->strokePath(shape(), QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    
        painter->restore();
    

    m_BoxSize is a member variable of my Item and set to QRectF(0, 0, 40, 40);
    and shape() is implemented like this:

        QPainterPath path;
        path.addRoundedRect(m_BoxSize, 5, 5);
        return path;
    

    When I add such an Item to my Scene, I'm getting a red rounded rect without infill.
    When I change painter->fillPath(shape(), gradient); to painter->fillPath(shape(), Qt::red); I'm getting a red rounded rect as expected.

    Can someone tell me my mistake?

    Thank you in advance and kind regards
    AlexRoot

    Edit: why aren't the code blocks working?

    [edit: Fixed coding tags, use ``` SGaist]
    ->Edit: Thank you :)


  • Lifetime Qt Champion

    Hi,

    Can you share the complete class code ?



  • Hi,
    yes, here it is:

    namespace Graphics
    {
        namespace Items
        {
            class ClassItem : public QGraphicsItem
            {
            public:
                ClassItem(const QColor &color, const QPoint &position, QGraphicsScene *scene);
    
                virtual QRectF boundingRect() const override;
                virtual QPainterPath shape() const override;
                virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
    
            private:
                QColor m_Color;
                QPoint m_Position;
                QRectF m_BoxSize;
                QPainterPath m_ShapePath;
                QLinearGradient m_TitleGradient;
                QGraphicsScene *m_pScene;
    
            public slots:
                void resize(const QRectF &newRect);
            };
        }
    }
    

    and the implementation

    
    Graphics::Items::ClassItem::ClassItem(const QColor &color, const QPoint &position, QGraphicsScene *scene) :
        m_Color(color),
        m_Position(position),
        m_pScene(scene)
    {
        setFlags(ItemIsSelectable | ItemIsMovable);
        setAcceptHoverEvents(true);
    
        m_TitleGradient.setCoordinateMode(QLinearGradient::ObjectBoundingMode);
        m_TitleGradient.setColorAt(0, Qt::red);
        m_TitleGradient.setColorAt(1, Qt::blue);
        resize(QRectF(0, 0, 40, 40));
    }
    
    void Graphics::Items::ClassItem::resize(const QRectF &newRect)
    {
        m_BoxSize = newRect;
        m_ShapePath = QPainterPath();
        m_ShapePath.setFillRule(Qt::WindingFill);
        m_ShapePath.addRoundedRect(newRect, 5, 5);
    
        m_TitleGradient.setStart(newRect.topLeft());
        m_TitleGradient.setFinalStop(newRect.bottomRight());
    }
    
    QPainterPath Graphics::Items::ClassItem::shape() const
    {
        return m_ShapePath;
    }
    
    void Graphics::Items::ClassItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        painter->save();
    
        painter->fillPath(m_ShapePath, m_TitleGradient);
        painter->strokePath(m_ShapePath, QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    
        painter->restore();
    }
    

    It looks very different now, I've reimplemented it. My problem persists:
    the example code "ignores" the fillPath line but
    painter->fillPath(m_ShapePath, Qt::green);
    works

    Kind regards
    AlexRoot



  • Any ideas on that?

    Tanks in advance and have a nice day :)



  • Check gradient fill mode:

    m_TitleGradient.setCoordinateMode(QLinearGradient::ObjectBoundingMode);
    // ...
    resize(QRectF(0, 0, 40, 40));
    

    ObjectBoundingMode accepts range 0 -> 1.
    Check LogicalMode (default mode).



  • Thank you for your answere. I've already tried that but it wasn't the solution. I've figured out that the problem occures when turning on OpenGL rendering. I guess it has to do with my hibryd graphic system. My main card has some serious problems so I can't run Optirun right now and I guess my secondary GPU does not support the required features (only OpenGL 3.X).
    I'm not shure about that but as I said: turning off the OpenGL rendering solved that problem for me. Maybe it helps others.

    Have a nice day everyone



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.