Search code examples
c++qtqwidgetqpixmap

QWidget render to QPixmap seems to ignore "border-radius" setting of stylesheet


I need to save a QPixmap from a QWidget (in my case a QPushButton), but it seems that some stylesheet settings are ignored.

Here is a sample code:

button = new QPushButton(QIcon(":/resources/icons/my_icon.png"), "Sample text", this);
button->setFocusPolicy(Qt::NoFocus);
button->setStyleSheet(" color: white; "
                      " background-color: gray; "
                      " font: 30px;"
                      " border-radius: 18px;");

button->setLayoutDirection(Qt::RightToLeft);
button->setIconSize(QSize(96, 96));
button->setGeometry(13, 10, 455, 100);

button->show();

QPixmap pixmap(button->size());
button->render(&pixmap);

The render method seems to ignore the " border-radius: 18px;" field of the stylesheet, I have tried to save the QPixmap to a file:

pixmap.save("test.png");

but the saved image is a rectangle, with no round border. The QPushButton has the correct round border when shown by the application.

Am I doing somethig wrong in using QWideget::render(...) method?


Solution

  • Your problem is that the QRegion in render func is a rectangular region.

    void QWidget::render(QPaintDevice *target, const QPoint &targetOffset = QPoint(), const QRegion &sourceRegion = QRegion(), QWidget::RenderFlags renderFlags = RenderFlags(DrawWindowBackground | DrawChildren))
    

    Qt dont know how to make a rounded rectangular region, you should compute manually this region you can start with this function ;)

    QRegion computeRegion(QPushButton*button, int radius)
    {
        QRegion region(0, 0, button->width(),button->height(), QRegion::Rectangle);
    
        /** top left */
        QRegion round (0, 0, 2*radius, 2*radius, QRegion::Ellipse);
        QRegion corner(0, 0, radius, radius, QRegion::Rectangle);
        region = region.subtracted(corner.subtracted(round));
    
        /** top right */
        round = QRegion(button->width()-2*radius, 0, 2*radius, 2*radius, QRegion::Ellipse);
        corner = QRegion(button->width()-radius, 0, radius, radius, QRegion::Rectangle);
        region = region.subtracted(corner.subtracted(round));
    
        /** bottom right */
        round = QRegion(button->width()-2*radius, button->height()-2*radius, 2*radius, 2*radius, QRegion::Ellipse);
        corner = QRegion(button->width()-radius, button->height()-radius, radius, radius, QRegion::Rectangle);
        region = region.subtracted(corner.subtracted(round));
    
        /** bottom left */
        round = QRegion(0, button->height()-2*radius, 2*radius, 2*radius, QRegion::Ellipse);
        corner = QRegion(0, button->height()-radius, radius, radius, QRegion::Rectangle);
        region = region.subtracted(corner.subtracted(round));
    
        return  region;
    }
    

    then use it in render function

    button->render(&pixmap,QPoint(),computeRegion(button,18));