在 PyQt 中将 Label 字体大小与布局同步
Syncing Label fontsize with layout in PyQt
通过signal/slots更改标签的字体大小以匹配其包含的布局大小的具体方法是什么?
下面是 QLabel
的解决方案,源自此处发布的解决方案:https://forum.qt.io/topic/36088/automatically-scale-text-in-qlabels/5。
这包括 resizeEvent
方法的重新实现,其中 QLabel
的字体大小根据其 contentRect
的大小更新。请注意,Qlabel 的 sizePolicy
必须设置为 Ignored
才能正常工作。
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_())
这导致:
更新 - resizeEvent 优化:
下面是 resizeEvent
方法的优化版本,应该会产生更好的性能。它大大减少了找到最佳字体大小值所需的迭代次数。不过我还没有对其进行广泛的测试。
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)
通过signal/slots更改标签的字体大小以匹配其包含的布局大小的具体方法是什么?
下面是 QLabel
的解决方案,源自此处发布的解决方案:https://forum.qt.io/topic/36088/automatically-scale-text-in-qlabels/5。
这包括 resizeEvent
方法的重新实现,其中 QLabel
的字体大小根据其 contentRect
的大小更新。请注意,Qlabel 的 sizePolicy
必须设置为 Ignored
才能正常工作。
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_())
这导致:
更新 - resizeEvent 优化:
下面是 resizeEvent
方法的优化版本,应该会产生更好的性能。它大大减少了找到最佳字体大小值所需的迭代次数。不过我还没有对其进行广泛的测试。
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)