Draw shadow around a top-level Framless QWidget with QLinearGradient ?



  • Hi.
    I have created a top-level QWidget (Qt::FramelessWindowHint) with resizing function.

    Now i want a shadow effect (Windows specific feature) around my widget without QGraphicsDropShadowEffect and affecting on child widget, instead via QLinearGradient on paintintg.

    I've tried this :
    Shadow
    but it is not what i want :
    Native-Shadow

    Painting :

    void Widget::paintEvent(QPaintEvent *) {
    	QPainter painter(this);
    	painter.setRenderHint(QPainter::Antialiasing);
    	painter.setPen(Qt::NoPen);
    
    
    	QLinearGradient gradient;
    
    	QColor grey1(150, 150, 150, 125);
    	QColor grey2(225, 225, 225, 125); 
    
    	gradient.setColorAt(0.0, grey1);
    	gradient.setColorAt(1.0, grey2);
    
    	painter.setBrush(QBrush(gradient));
    
    
    	QPointF topLeft(0, 0);
    	QPointF bottomRight(width(), height());
    	QRectF rect(topLeft, bottomRight);
    	painter.drawRoundRect(rect, 0.0, 0.0);
    
    	QBrush brush2(QColor("#FFFFFF"), Qt::SolidPattern);
    	painter.setBrush(brush2);
    
    	QPointF topLeft2(5, 5);
    	QPointF bottomRight2(width() - 5, height() - 5);
    	QRectF rect2(topLeft2, bottomRight2);
    	painter.drawRoundRect(rect2, 0.0, 0.0);
    }
    

    What did i miss in code ?


  • Qt Champions 2016

    Hi
    Im slightly confused.
    You cannot draw outside your widget so im not sure
    how u be able to draw dropshadow as it sort of interacts with other windows outside
    of the Widgets clientarea.

    Did I miss something?



  • Hi. @mrjj
    No. It's not outside the widget. it's a little hack on widget.
    If you look at the paintEvent first i drew the linergradient and then i drew the actual widget from (5,5) to (width() -5, height() -5) :

    QBrush brush2(QColor("#FFFFFF"), Qt::SolidPattern);
        painter.setBrush(brush2);
    
        QPointF topLeft2(5, 5);
        QPointF bottomRight2(width() - 5, height() - 5);
        QRectF rect2(topLeft2, bottomRight2);
        painter.drawRoundRect(rect2, 0.0, 0.0);
    

    Now the problem is the linergradiant shadow is not desired.



  • @IMAN4K

    Hi,Did you add the start and end points for QLinearGradient?

    ex) QLinearGradient gradient(QPointF(0, 0), QPointF(width(), height()));



  • Ok.
    I made one :

    QPainter painter(this);
    	painter.setPen(Qt::NoPen);
    
    	int margin = 10;
    	QColor start(151, 151, 151, 32);
    	QColor end(255, 255, 255, 0);
    	QPointF right0(width() - margin, height() / 2);
    	QPointF right1(width(), height() / 2);
    	QPointF left0(margin, height() / 2);
    	QPointF left1(0, height() / 2);
    	QPointF top0(width() / 2, margin);
    	QPointF top1(width() / 2, 0);
    	QPointF bottom0(width() / 2, height() - margin);
    	QPointF bottom1(width() / 2, height());
    	QPointF bottomright0(width() - margin, height() - margin);
    	QPointF bottomright1(width(), height());
    	QPointF bottomleft0(margin, height() - margin);
    	QPointF bottomleft1(0, height());
    	QPointF topLeft0(margin, margin);
    	QPointF topleft1(0, 0);
    	QPointF topright0(width() - margin, margin);
    	QPointF topright1(width(), 0);
    
    	QLinearGradient gradient;
    	gradient.setColorAt(0.0, start);
    	gradient.setColorAt(1.0, end);
    	// right
    	gradient.setStart(right0);
    	gradient.setFinalStop(right1);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(QPointF(margin, margin), QPointF(width(), height()-margin)), 0.0, 0.0);
    	// left
    	gradient.setStart(left0);
    	gradient.setFinalStop(left1);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(QPointF(width() - margin, margin), QPointF(0, height()-margin)), 0.0, 0.0);
    	// top
    	gradient.setStart(top0);
    	gradient.setFinalStop(top1);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(QPointF(width() - margin, 0), QPointF(margin, height()-margin)), 0.0, 0.0);
    	// bottom 
    	gradient.setStart(bottom0);
    	gradient.setFinalStop(bottom1);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(QPointF(margin, margin), QPointF(width() - margin, height() )), 0.0, 0.0);
    	// bottom right
    	gradient.setStart(bottomright0);
    	gradient.setFinalStop(bottomright1);
    	gradient.setColorAt(0.6, end);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
    	// bottom left
    	gradient.setStart(bottomleft0);
    	gradient.setFinalStop(bottomleft1);
    	gradient.setColorAt(0.6, end);
    	painter.setBrush(QBrush(gradient));
    	painter.drawRoundRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
    	// top left
    	gradient.setStart(topLeft0);
    	gradient.setFinalStop(topleft1);
    	painter.setBrush(QBrush(gradient));
    	gradient.setColorAt(0.6, end);
    	painter.drawRoundRect(QRectF(topLeft0, topleft1), 0.0, 0.0);
    	// top right
    	gradient.setStart(topright0);
    	gradient.setFinalStop(topright1);
    	painter.setBrush(QBrush(gradient));
    	gradient.setColorAt(0.6, end);
    	painter.drawRoundRect(QRectF(topright0, topright1), 0.0, 0.0);
    	// actual widget
    	painter.setBrush(QBrush("#FFFFFF"));
    	painter.drawRoundRect(QRectF(QPointF(margin, margin), QPointF(width() - margin, height() - margin)), 0.0, 0.0);
    

    But it doesn't seems realistic !
    Could you guys tell me how could it be better ?
    Thanks a lot.


  • Qt Champions 2016

    I think that one looks nice.



  • Ok.
    It might get better in the future !

    If you wan to get ride of QGraphicsDropShadowEffect :

    void drawShadow(QPainter &_painter, qint16 _margin, qreal _radius,
    QColor _start, QColor _end, qreal _startPosition, qreal _endPosition0, qreal _endPosition1, qreal _width, qreal _height) {
    	_painter.setPen(Qt::NoPen);
    
    	QLinearGradient gradient;
    	gradient.setColorAt(_startPosition, _start);
    	gradient.setColorAt(_endPosition0, _end);
    	// Right
    	QPointF right0(_width - _margin, _height / 2);
    	QPointF right1(_width, _height / 2);
    	gradient.setStart(right0);
    	gradient.setFinalStop(right1);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(QPointF(_width - _margin*_radius, _margin), QPointF(_width, _height - _margin)), 0.0, 0.0);
    	// Left
    	QPointF left0(_margin, _height / 2);
    	QPointF left1(0, _height / 2);
    	gradient.setStart(left0);
    	gradient.setFinalStop(left1);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(QPointF(_margin *_radius, _margin), QPointF(0, _height - _margin)), 0.0, 0.0);
    	// Top
    	QPointF top0(_width / 2, _margin);
    	QPointF top1(_width / 2, 0);
    	gradient.setStart(top0);
    	gradient.setFinalStop(top1);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(QPointF(_width - _margin, 0), QPointF(_margin, _margin)), 0.0, 0.0);
    	// Bottom
    	QPointF bottom0(_width / 2, _height - _margin);
    	QPointF bottom1(_width / 2, _height);
    	gradient.setStart(bottom0);
    	gradient.setFinalStop(bottom1);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(QPointF(_margin, _height - _margin), QPointF(_width - _margin, _height)), 0.0, 0.0);
    	// BottomRight
    	QPointF bottomright0(_width - _margin, _height - _margin);
    	QPointF bottomright1(_width, _height);
    	gradient.setStart(bottomright0);
    	gradient.setFinalStop(bottomright1);
    	gradient.setColorAt(_endPosition1, _end);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(bottomright0, bottomright1), 0.0, 0.0);
    	// BottomLeft
    	QPointF bottomleft0(_margin, _height - _margin);
    	QPointF bottomleft1(0, _height);
    	gradient.setStart(bottomleft0);
    	gradient.setFinalStop(bottomleft1);
    	gradient.setColorAt(_endPosition1, _end);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(bottomleft0, bottomleft1), 0.0, 0.0);
    	// TopLeft
    	QPointF topleft0(_margin, _margin);
    	QPointF topleft1(0, 0);
    	gradient.setStart(topleft0);
    	gradient.setFinalStop(topleft1);
    	gradient.setColorAt(_endPosition1, _end);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(topleft0, topleft1), 0.0, 0.0);
    	// TopRight
    	QPointF topright0(_width - _margin, _margin);
    	QPointF topright1(_width, 0);
    	gradient.setStart(topright0);
    	gradient.setFinalStop(topright1);
    	gradient.setColorAt(_endPosition1, _end);
    	_painter.setBrush(QBrush(gradient));
    	_painter.drawRoundRect(QRectF(topright0, topright1), 0.0, 0.0);
    	// Widget
    	_painter.setBrush(QBrush("#FFFFFF"));
    	_painter.setRenderHint(QPainter::Antialiasing);
    	_painter.drawRoundRect(QRectF(QPointF(_margin, _margin), QPointF(_width - _margin, _height - _margin)), _radius, _radius);
    }
    

    drawShadow(painter, 10, 2.0, QColor(120, 120, 120, 32), QColor(255, 255, 255, 0), 0.0, 1.0, 0.6, width(), height());
    don't forget setAttribute(Qt::WA_TranslucentBackground);
    Final Resualt : https://onedrive.live.com/?cid=8882d1e3bc0f61ab&id=8882D1E3BC0F61AB!7415&authkey=!AH66ZieCJDqvXhk



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