Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
562 views
in Technique[技术] by (71.8m points)

python - Syncing Label fontsize with layout in PyQt

What is the concrete way to change the font size of a label to match the layout size its contained in through signal/slots?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Below is a solution, for a QLabel, derived from the solution posted here: https://forum.qt.io/topic/36088/automatically-scale-text-in-qlabels/5.

This consists in a reimplementation of the resizeEvent method where the font size of the QLabel is updated according to the size of its contentRect. Note that the sizePolicy of the Qlabel has to be set to Ignored for this to work properly.

import sys
from PyQt4 import QtGui     

class myQLabel(QtGui.QLabel):
    def __init__(self, *args, **kargs):
        super(myQLabel, self).__init__(*args, **kargs)

        self.setSizePolicy(QtGui.QSizePolicy(QtGui.QSizePolicy.Ignored,
                                             QtGui.QSizePolicy.Ignored))  

        self.setMinSize(14)

    def setMinSize(self, minfs):        

        f = self.font()
        f.setPixelSize(minfs)
        br = QtGui.QFontMetrics(f).boundingRect(self.text())

        self.setMinimumSize(br.width(), br.height())

    def resizeEvent(self, event):
        super(myQLabel, self).resizeEvent(event)

        if not self.text():
            return

        #--- fetch current parameters ----

        f = self.font()
        cr = self.contentsRect()

        #--- find the font size that fits the contentsRect ---

        fs = 1                    
        while True:

            f.setPixelSize(fs)
            br =  QtGui.QFontMetrics(f).boundingRect(self.text())

            if br.height() <= cr.height() and br.width() <= cr.width():
                fs += 1
            else:
                f.setPixelSize(max(fs - 1, 1)) # backtrack
                break  

        #--- update font size ---

        self.setFont(f)     


class myApplication(QtGui.QWidget):
    def __init__(self, parent=None):
        super(myApplication, self).__init__(parent)

        #---- Prepare a Layout ----

        grid = QtGui.QGridLayout()  

        for i in range(3):
            grid.addWidget(myQLabel('some text'), i, 0)  
            grid.setRowStretch(i, i+1)
            grid.setRowMinimumHeight(i, 25)

        self.setLayout(grid)
        self.resize(500, 300)


if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)

    instance = myApplication()  
    instance.show()    

    sys.exit(app.exec_())

Which results in:

enter image description here

Update - Optimization of resizeEvent :

Below is an optimized version of the resizeEvent method that should yield better performances. It drastically reduces the number of iteration required to find the optimal value of the font size. I haven't tested it extensively though.

def resizeEvent(self, event):
    super(myQLabel, self).resizeEvent(event)        

    if not self.text():
        return

    #--- fetch current parameters ----

    f = self.font()
    cr = self.contentsRect()

    #--- iterate to find the font size that fits the contentsRect ---

    dw = event.size().width() - event.oldSize().width()   # width change
    dh = event.size().height() - event.oldSize().height() # height change

    fs = max(f.pixelSize(), 1)        
    while True:

        f.setPixelSize(fs)
        br =  QtGui.QFontMetrics(f).boundingRect(self.text())

        if dw >= 0 and dh >= 0: # label is expanding

            if br.height() <= cr.height() and br.width() <= cr.width():
                fs += 1
            else:
                f.setPixelSize(max(fs - 1, 1)) # backtrack
                break                    

        else: # label is shrinking

            if br.height() > cr.height() or br.width() > cr.width():
                fs -= 1
            else:
                break

        if fs < 1: break

    #--- update font size ---           

    self.setFont(f)   

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...