Understanding QRadialGradient::radius() in Qt GUI Programming


Purpose

  • The radius() function is specifically used to retrieve the radius of this circular area in logical coordinates. These coordinates are relative to the widget or item where the gradient is applied, providing a consistent and scalable way to define the gradient's size.
  • In Qt, QRadialGradient creates a brush with a radial color effect, where colors transition outward from a focal point within a circular area.

How it Works

    • You typically create a QRadialGradient object using constructors like:
      QRadialGradient gradient(center, radius);
      
      • center (of type QPointF) specifies the center point of the gradient in logical coordinates.
      • radius (a qreal value) defines the radius of the circular area.
  1. Accessing the Radius

    • Once you have the QRadialGradient object, use radius() to get the current radius value:
      double currentRadius = gradient.radius();
      

Key Points

  • You can modify the radius after creating the QRadialGradient object using setRadius(newRadius). This allows for dynamic adjustments to the gradient's size.
  • Logical coordinates are unit-less and independent of the widget's or item's physical size. This allows the gradient to scale appropriately with the widget or item.
  • The radius determines the extent of the color transition in the gradient. A larger radius creates a wider gradient effect, while a smaller radius results in a more focused gradient.

Example

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QRadialGradient>

class MyWidget : public QWidget {
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);

        // Create a radial gradient with a center and radius
        QPointF center(width() / 2, height() / 2); // Center at widget's center
        double radius = std::min(width(), height()) / 2; // Radius half the widget's size

        QRadialGradient gradient(center, radius);
        gradient.setColorAt(0.0, Qt::red);
        gradient.setColorAt(1.0, Qt::yellow);

        // Use the gradient as the fill brush
        painter.setBrush(gradient);
        painter.drawRect(0, 0, width(), height());
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}


Dynamically Updating Radius based on User Interaction

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QRadialGradient>
#include <QSlider>

class MyWidget : public QWidget {
    Q_OBJECT

public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {
        slider = new QSlider(Qt::Horizontal, this);
        slider->setRange(10, width() / 2); // Set range based on widget width
        slider->setValue(width() / 4);    // Initial radius

        connect(slider, &QSlider::valueChanged, this, &MyWidget::updateRadius);
    }

signals:
    void radiusChanged(double newRadius);

private slots:
    void updateRadius(int value) {
        radius = value;
        emit radiusChanged(radius); // Emit signal for potential updates
        update();                     // Trigger repaint
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);

        QPointF center(width() / 2, height() / 2);

        // Use the current radius retrieved from the slider
        QRadialGradient gradient(center, radius);
        gradient.setColorAt(0.0, Qt::blue);
        gradient.setColorAt(1.0, Qt::white);

        painter.setBrush(gradient);
        painter.drawRect(0, 0, width(), height());
    }

    QSlider* slider;
    double radius = width() / 4; // Initial radius
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

This code creates a slider that allows the user to adjust the radius of the radial gradient. As the slider value changes, the updateRadius slot is called, which updates the radius member variable and triggers a repaint.

Using Elliptical Gradients

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QRadialGradient>

class MyWidget : public QWidget {
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);

        QPointF center(width() / 2, height() / 3); // Center shifted upwards

        // Create an elliptical gradient with different x and y radii
        double xRadius = width() / 3;
        double yRadius = height() / 2;
        QRadialGradient gradient(center, xRadius, yRadius, QRadialGradient::Ellipse);
        gradient.setColorAt(0.0, Qt::green);
        gradient.setColorAt(1.0, Qt::lightGray);

        painter.setBrush(gradient);
        painter.drawRect(0, 0, width(), height());
    }
};

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MyWidget widget;
    widget.show();
    return app.exec();
}

This example demonstrates creating an elliptical radial gradient by specifying different values for xRadius and yRadius in the constructor. This creates an oval-shaped gradient effect.

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QRadialGradient>

class MyWidget : public QWidget {
public:
    MyWidget(QWidget *parent = nullptr) : QWidget(parent) {}

protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);

        QPointF center(width() / 2, height() / 2);
        double radius = std::min(width(), height()) / 2;

        QRadialGradient gradient(center, radius);
        gradient.setColorAt(0.2, Qt::purple);
        gradient.setColorAt(0.5, Qt::orange);
        gradient.setColorAt(1.0, Qt::yellow); // Additional stop for smoother transition

        painter.setBrush(gradient);
        painter.drawRect(0, 0, width(), height());
    }
};

int main(int argc, char *argv[]) {
    QApplication app


Scaling the Widget/Item

  • This approach is simple but might not be suitable if you need precise control over the gradient's size independent of the widget's dimensions.
  • If you want the gradient to adapt automatically to the size of the widget or item where it's applied, you can scale the widget/item itself. Qt's layout system and scaling mechanisms can handle this effectively.

Using setTransform() on the QPainter Object

  • You can use the setTransform() function on the QPainter object to scale the gradient within the widget/item's coordinate system. This allows for more fine-grained control over the gradient's size relative to the widget.
void paintEvent(QPaintEvent *event) override {
    QPainter painter(this);

    QPointF center(width() / 2, height() / 2);
    double baseRadius = 50.0; // Fixed base radius

    QRadialGradient gradient(center, baseRadius);
    gradient.setColorAt(0.0, Qt::blue);
    gradient.setColorAt(1.0, Qt::white);

    // Scale the painter by a factor to adjust the gradient size
    double scaleFactor = width() / (2.0 * baseRadius); // Example scaling based on widget width
    painter.setTransform(QTransform::fromScale(scaleFactor, scaleFactor));

    painter.setBrush(gradient);
    painter.drawRect(0, 0, width(), height());
}

In this example, the scaleFactor is calculated based on the widget's width and the base radius, ensuring the gradient covers most of the widget's area while maintaining a fixed base radius value.

  • For more complex scenarios, you could create a custom gradient class that encapsulates the logic for defining and managing the radial gradient. This class could provide methods to set the center, radius, and other properties, offering a more object-oriented approach.