Syncing Label fontsize with layout in PyQt

后端 未结 1 774
粉色の甜心
粉色の甜心 2020-12-20 08:36

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

相关标签:
1条回答
  • 2020-12-20 09:16

    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:

    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)   
    
    0 讨论(0)
提交回复
热议问题