How to calculate setPen+drawPath dimensions?



  • I want to paint outline around text in QLabel.
    I can't start with x=0, because left side of the outline will be lost, I also have to add few pixels to y, otherwise outline at the bottom will be lost. But how do I calculate this offset precisely?
    Adding outline_width to all sides is taking up unnecessary space because of 10px brush only 3-5 goes into outline, the rest is hidden behind/inside letters; I need QLabel to take up space as little as possible.

    N = ?
    N2 = ?
    
    self.setFixedSize(self.fontMetrics().width(self.text) + N*2, self.fontMetrics().height() + N2*2)
    
    x = 0 + N
    y = self.fontMetrics().ascent() + N2
    
    outline_width = 10
    
    painter = QPainter(self)
    text_path = QPainterPath()
    text_path.addText(x, y, font, text)
    
    outline_brush = QBrush(QColor(0, 0, 0, alpha), Qt.SolidPattern)		
    outline_pen = QPen(outline_brush, outline_width, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)
    
    painter.setPen(outline_pen)
    painter.drawPath(text_path)
    
    painter.setPen(QColor(255, 255, 255, 255))
    painter.drawText(x, y, text)
    

  • Moderators

    @porsol
    translating (adding for top/left, subtracting for bottom/right) by the half stroke width should do it:

    qFloor( pen.widthF() / 2.0 )
    

    See Qt's coordinate system.



  • @raven-worx said in How to calculate setPen+drawPath dimensions?:

    translating (adding for top/left, subtracting for bottom/right) by the half stroke width should do it:

    Unfortunately no, it doesn't. Out of the width of the brush less than half goes to actual outline, the rest goes under the text and inside the letters. So when N2 == qFloor( pen.widthF() / 2.0 ) - it gobbles up some free space on top taking it from the bottom, N == qFloor( pen.widthF() / 2.0 ) does the same horizontally.


  • Moderators

    @porsol
    i am afraid i don't quite understand your issue then. can you post a screenshot?



  • @raven-worx alt text

    I switched the brush to red and put another smaller black brush for visibility.
    To see the difference you should zoom the pic like 1000% in non-browser image-viewer.
    green vLine is separator between QLabels

    pen.width() == 10
    N = N2 = pen.width() / 2 # int still
    x = 0 + N
    y = self.fontMetrics().ascent() + N2
    
    # top example in pic
    # not enough pixels in width, too much in height
    self.setFixedSize(self.fontMetrics().width(self.text) + N*2,text_height + N*2)
    text_path.addText(x, y, font, text)
    painter.drawText(x, y, text)
    
    # bottom example in pic
    # adding/subtracting arbitrary pixels shows how it looks whole
    self.setFixedSize(self.fontMetrics().width(self.text) + N*2 + 10,text_height + N*2)
    text_path.addText(x+5, y-5, font, text)
    painter.drawText(x+5, y-5, text)
    

    I can with trial and error find the exact number of px I should add/subtract for a specific font and outline_width - but that doesn't work for me. Font and outline should be adjustable.


  • Moderators

    @porsol said in How to calculate setPen+drawPath dimensions?:

    I need QLabel to take up space as little as possible.

    according to your screenshot you can calculate the values which take up the inner padding by the following:

    int labelMargin = label->margin();
    int labelIndent = label->indent();
    int frameWidth = label->frameWidth();
    
    // see http://doc.qt.io/qt-5/qlabel.html#indent-prop
    if( labelIndent < 0 )
    {
        if( frameWidth <= 0 )
            labelIndent = 0;
        else
        {
            QFontMetrics fm(label->font());
            labelIndent = ( fm.width("x") / 2.0 );
        }
    }
    

Log in to reply
 

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