我试图用PySide6的QPainter和QFontMetrics绘制多个文本段落。我想用相同的间距画他们,如果我把他们都画成一个单一的文本,但是行距不太正确。
在下面的例子中,字体度量表示字体的行距是17。当我测量一行文本时,边框实际上是17像素高。然而,当我测量两行文本时,边框是35像素高,而不是34像素。额外的像素来自哪里,我能在字体或字体度量的某些属性上看到它吗?
from PySide6.QtGui import QFont, QFontMetrics
from PySide6.QtWidgets import QApplication
app = QApplication()
font = QFont()
metrics = QFontMetrics(font)
print(metrics.lineSpacing()) # 17
print(metrics.boundingRect(0, 0, 100, 100, 0, 'A').height()) # 17
print(metrics.boundingRect(0, 0, 100, 100, 0, 'A\nB').height()) # 35 != 17 * 2
print(metrics.leading()) # 0
print(metrics.ascent()) # 14
print(metrics.descent()) # 3顺便说一句,它并不总是额外的一个像素。如果我使字体变大,额外的空间就会增加。
更新
我以为我已经用音乐人的建议从QFontMetrics转换到QFontMetricsF来解决这个问题了,但还是有区别的。
from PySide6.QtCore import QRectF
from PySide6.QtGui import QFont, QFontMetricsF
from PySide6.QtWidgets import QApplication
app = QApplication()
font = QFont()
metrics = QFontMetricsF(font)
print(metrics.height()) # 16.8125
print(metrics.boundingRect(QRectF(0, 0, 100, 100),
0,
'A').getCoords()) # (0.0, 0.0, 9.9375, 16.8125)
print(metrics.boundingRect(QRectF(0, 0, 100, 100),
0,
'A\nB').getCoords()) # (0.0, 0.0, 9.9375, 34.8125)
# Note the height of that rect doesn't match the next calculation.
print(metrics.height() + metrics.lineSpacing()) # 34.046875
# I can't see any combination of these numbers that makes 34.8125
print(metrics.lineSpacing()) # 17.234375
print(metrics.leading()) # 0.421875
print(metrics.ascent()) # 13.984375
print(metrics.descent()) # 2.828125发布于 2022-10-29 21:10:05
首先,字体度量的边框的高度并不取决于所使用的字符,而是取决于字体规范。
两行文本没有单行边框的height()的两倍:相反,您必须考虑lineSpacing()。
在实践中,圆角的高度通常是以下的总和:
或类似地,以下两者之和:
注意,很明显,行数取决于输入文本和给定的选项,例如,如果启用了word包装,并且任何源行都不适合给定的源矩形。
还要考虑的是,大多数字体都是矢量的,这意味着它们的坐标和度量是成比例的,并且是浮点值。相反,由于简单和优化的原因,QFontMetrics使用整数值,因此在点大小不提供四舍五入值的情况下,可能会得到不一致的结果:非整数通常是“泛”的(如python中的int() )。
在您的示例中,leading可能超过0(但仍然小于1),因此无法得到上述高度的适当和。
具体来说,QFontMetrics.boundingRect()返回由计算格式文本的QRectF.toAlignedRect()生成的QRect,该文本始终是“完全包含此矩形的最小可能整数矩形”。
如果需要获得精确的坐标,则需要使用QFontMetricsF,这是默认基本QFontMetrics的浮点对应。
也就是说,如果您计划使用QPainter绘制格式化文本,那么可以考虑使用QTextDocument或至少使用QTextLayout,这与标准的Qt文本绘图是一致的,并且通常更快、更可靠和“更简单”(嗯,一旦您了解了它)。虽然它看起来比需要的要复杂一些,但它实际上是Qt在调用boundingRect()时所做的,所以如果您需要定制绘图,那么QTextLayout选项实际上更好,特别是如果您可以将它与一些智能缓存(参见QPicture)结合起来,以避免常见的python瓶颈。
https://stackoverflow.com/questions/74246330
复制相似问题