Home > Mobile >  QGraphicsView: Paint Rectangular Gradient
QGraphicsView: Paint Rectangular Gradient

Time:05-28

I'm trying to paint a rectangular gradient as the background for a QGraphicsView.

This image is an example of what I'm trying to achieve:

enter image description here

Notice the light gradient around the borders.

I tried using 4 QLinearGradients going from each border of the window to the opposite(From right to left, from top to bottom and so on). I don't think this approach is very efficient(painting so many gradient objects). Maybe a single QLinearGradient with the Spread set to ReflectSpread is enough, but I have a positioning issue. The idea is that the gradient should be like a visor, like the frame of a camera. It should always look the same regardless of QGraphicsView size or scale.

This is the code for the QLinearGradient:

    QLinearGradient lGrad;
    lGrad.setSpread(QGradient::ReflectSpread);
    lGrad.setStart(0, 500);
    lGrad.setColorAt(0, Qt::red);
    lGrad.setColorAt(1, Qt::blue);

    painter->fillRect(rect, lGrad);

I tried using a stylesheet around the border but it doesn't give me the desired results. It seems that gradients cannot be applied to borders, only to tooltips. Minimal example:

#include <QGraphicsView>

// View
class View : public QGraphicsView
{
    Q_OBJECT
    public:
     explicit View(QWidget* parent = nullptr)
     {
         // Stylesheet
         setStyleSheet(
             "border-left:40px solid qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
             "border-right:40px solid qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
             "border-top:40px solid qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
             "border-bottom:40px solid qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
             "border-radius: 0.5px;"
             "padding: 1px;"
             "margin: 0px;"
             "spacing: 0px;"
             );

        // Hidden because the stylesheet adds colors to them
         setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff);
         setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

         setDragMode(QGraphicsView::ScrollHandDrag);
         setBackgroundBrush(QColor(35, 41, 56));
         setCacheMode(CacheBackground);
         setViewportUpdateMode(BoundingRectViewportUpdate);
         setRenderHint(QPainter::Antialiasing);
         setTransformationAnchor(AnchorUnderMouse);
         scale(qreal(0.8), qreal(0.8));
         setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
     }

     void mousePressEvent(QMouseEvent *event) override
     {
         QGraphicsView::mousePressEvent(event);
         if (event->button() == Qt::LeftButton)
         {
             _clickPos = mapToScene(event->pos());
         }
     }

     void mouseMoveEvent(QMouseEvent *event) override
     {
         QGraphicsView::mouseMoveEvent(event);
         if (scene()->mouseGrabberItem() == nullptr && event->buttons() == Qt::LeftButton)
         {
             if ((event->modifiers() & Qt::ShiftModifier) == 0)
             {
                 QPointF difference = _clickPos - mapToScene(event->pos());
                 setSceneRect(sceneRect().translated(difference.x(), difference.y()));
             }
         }
     }
}
// Main
#include <QMainWindow>
#include <QGraphicsScene>

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

    auto scene = new QGraphicsScene;

    auto view = new View;
    view->setScene(scene);

    auto window = new QMainWindow;
    window->setCentralWidget(view);
    window->show();

    return app.exec();
}

CodePudding user response:

I tried to create it by using Stylesheet and this is my result:

enter image description here

I add one graphicsView Widget in my centralwidget and add this Stylesheet:

border-left:20px solid qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(32, 180, 214,150), stop:1 rgba(0, 0, 0, 0) );

border-right:20px solid qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(32, 180, 214,150), stop:1 rgba(0, 0, 0, 0) );

border-top:20px solid qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(32, 180, 214,150), stop:1 rgba(0, 0, 0, 0) );

border-bottom:20px solid qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(32, 180, 214,150), stop:1 rgba(0, 0, 0, 0) );

border-radius: 0.5px;
padding: 1px;
margin: 0px;
spacing: 0px;

I tried to get your color, but if you play with its RGB, you can get the color you want. I think this is the cleanest solution possible because by changing the size of the view, everything changes the same and the Style remains constant.

enter image description here

Edited and Updated: you shouldn't add setBackgroundBrush(QColor(35, 41, 56)); to your QGraphicsView and View class . I remove this line and instead I add this in MainWindow as setStyleSheet. like this :

in View class :

View::View()
{
    // Stylesheet
    setStyleSheet(
        "border-left:40px solid qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
        "border-right:40px solid qlineargradient(spread:pad, x1:1, y1:0, x2:0, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
        "border-top:40px solid qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
        "border-bottom:40px solid qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0,150), stop:1 rgba(0, 0, 0, 0) );"
        "border-radius: 0.5px;"
        "padding: 1px;"
        "margin: 0px;"
        "spacing: 0px;"
        );

// Hidden because the stylesheet adds colors to them
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    setDragMode(QGraphicsView::ScrollHandDrag);
// setBackgroundBrush(QColor(35, 41, 56));
    setCacheMode(CacheBackground);
    setViewportUpdateMode(BoundingRectViewportUpdate);
    setRenderHint(QPainter::Antialiasing);
    setTransformationAnchor(AnchorUnderMouse);
    scale(qreal(0.8), qreal(0.8));
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
}

and in MainWindow class:

MainWindow::MainWindow(QWidget *parent):
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setStyleSheet("background-color: rgb(35, 41, 43);");

    auto  scene = new QGraphicsScene;
    auto  view  = new View;
    view->setScene(scene);
    setCentralWidget(view);
}

This is The Result:

enter image description here

  • Related