Search code examples
qt4antialiasingqpainterqtstylesheets

Qt Antialiasing with QPainter versus QStyleSheets


Here are two QWidget painted black. The painting on left QWidget was performed using QPainter (overriding ::paintEvent(...)). The right widget was "painted" using QStyleSheet.

enter image description here

This work was done in PyQt4 (Python: 2.7.11+/Qt: 4.8.7/PyQt4: 4.11.4). But you I have achieved the same result using PyQt5 and C++ Qt4/Qt5.

The code I used to paint the left QWidget is

def paintEvent( self, pEvent ) :

    painter = QPainter( self )
    painter.setRenderHints( QPainter.HighQualityAntialiasing )

    painter.setPen( Qt.black )
    painter.setBrush( Qt.black )

    painter.drawRoundedRect( self.rect(), 10.0, 10.0 )

    painter.end()

    pEvent.accept()

The stylesheet used on the right widget is

setStyleSheet( "border-radius: 10px; border: 1px solid black; background: black;" )

Why is there a difference between the two, especially the rounded part drawn by QStyleSheet far more smoother than the one done by QPainter despite using QPainter.HighQualityAntialiasing render hint? You could use just QPainter.Antialiasing or QPainter.TextAntialiasing and still the situation does not improve.


Solution

  • By using a color to initialize the QPen you select a pen (and therefor a border) width of 0; my guess is that you should set it to 1 px as in the stylesheet to get the same result. Try

    painter.setPen( QPen(Qt.black, 1) )
    

    Edit: I just came about some old code of mine, implementing rounded borders for QLabels. I was forced to correct the QRect for the pen width, else I got similarly ugly results. The implementation is placed in a custom style; the shadow color is set to the appropriate frame color:

    void MyStyle::drawControlHeaderFrame(const QStyleOptionFrameV3* option,
        QPainter* painter, const QWidget* widget) const
    {
        QPalette::ColorGroup cg = QPalette::Active;
    
        if(!(option->state & QStyle::State_Enabled))
            cg = QPalette::Disabled;
        else if(!(option->state & QStyle::State_Active))
            cg = QPalette::Inactive;
    
        const int lineWidth = 2, frameAdjustment = lineWidth / 2;
        QRect rect(option->rect);
        //Adjust for pen width
        rect.adjust(frameAdjustment, frameAdjustment, -frameAdjustment, -frameAdjustment);
    
        QPen pen(option->palette.color(cg, QPalette::Shadow));
        pen.setWidth(lineWidth);
    
        painter->save();
        {
            painter->setRenderHint(QPainter::Antialiasing);
            painter->setPen(pen);
            painter->drawRoundedRect(rect, 9, 9);
        }
        painter->restore();
    }