Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

cast QGraphicsEffect* to QGraphicsColorizeEffect* makes program crash.



  • Hi.
    I am trying to get my head around QGraphicsEffect.
    I have a bunch of QWidgets and I want to put QGraphicsColorizeEffect on some of them some of the time. So I need to be able to set and remove the effect dynamically.
    I can set an effect on a QWidget with QWidget::setGraphicsEffect(), which (I think) works on all types of effects. But there is no function to remove the effect.
    But then I thought maybe I can just add an effect to all the widgets, and then use setStrength().
    QWidget::setGraphicsEffect() works on all effects and QWidget::graphicsEffect() returns a pointer to a QGraphicsEffect, but setStrength belongs to QGraphicsColorizeEffect.
    So maybe I should cast it? But then the program crashes.
    My code looks like this:

    void activateEffect(QWidget* widget)
    {
        QGraphicsColorizeEffect* effect;
        effect = (QGraphicsColorizeEffect*) current->graphicsEffect();
        effect->setStrength(0);
    
        if (!widget->graphicsEffect())
            widget->setGraphicsEffect(new QGraphicsColorizeEffect(widget));
    
        effect = (QGraphicsColorizeEffect*) widget->graphicsEffect();
        effect->setStrength(1);
    
        current = widget;
    }
    

    So I guess my questions are

    • Is this the right way to do this?
    • Why is it crashing. It looks like it crashes at the line with the casting
    effect = (QGraphicsColorizeEffect*) current->graphicsEffect();
    

  • Lifetime Qt Champion

    Are you sure current is valid? I would guess no. Also I would suggest you to not use C-style casts but the C++ equivalents like const_cast<>, static_cast<>, dynamic_cast<> or reinterpret_cast<> (better avoid using reinterpret cast when possible)



  • @Jakob-Clausen said in cast QGraphicsEffect* to QGraphicsColorizeEffect* makes program crash.:

    effect = (QGraphicsColorizeEffect*) current->graphicsEffect();

    As @Christian-Ehrlicher says. Replace with:

    Q_ASSERT(current);
    effect = dynamic_cast<QGraphicsColorizeEffect*>(current->graphicsEffect());
    Q_ASSERT(effect);
    

    What happens?



  • Christian Ehrlicher: Thank you for your input. I think you are right. I will try it on monday. Do you think this is the right way to do something like this?

    JonB: Also thank you for your input. I will also try this on monday.

    Have a nice weekend.


  • Lifetime Qt Champion

    Hi
    Just as info

    You can turn off an effect by calling setGraphicsEffect with nullptr

    Its logic is like this

    void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
    {
        Q_D(QWidget);
        if (d->graphicsEffect == effect)
            return;
        if (d->graphicsEffect) {
            d->invalidateBackingStore(rect());
            delete d->graphicsEffect;
            d->graphicsEffect = 0;
        }
        if (effect) {
            // Set new effect.
            QGraphicsEffectSourcePrivate *sourced = new QWidgetEffectSourcePrivate(this);
            QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
            d->graphicsEffect = effect;
            effect->d_func()->setGraphicsEffectSource(source);
            update();
        }
        d->updateIsOpaque();
    }
    

    so nothing bad happens to give it a null pointer since it will delete the one it has.

    But if you only use QGraphicsColorizeEffect, i like your idea with setStrength() as
    then we dont go around deleting and creating QGraphicsColorizeEffect over and over.



  • Thank you all for your help.
    current was not valid. It was a brainfart on my part.
    But thank you very much for your input.


Log in to reply