QFont点大小设为-1时QFontMetrics::horizontalAdvance()返回值异常咨询
QFont使用点大小-1时QFontMetrics::horizontalAdvance返回值偏大的问题分析
当构造QFont实例时传入点大小参数-1(根据Qt文档,该值会将字体点大小设置为系统相关的默认值),调用QFontMetrics{font}.horizontalAdvance()返回的数值会比直接使用系统默认点大小(通过QApplication::font().pointSize()获取)时更大,演示代码如下:
class QTextWidthTest : public QWidget { public: QTextWidthTest() { this->setFixedSize(600, 400); } private: void _paintExample(QPainter& painter, const int pointSize, const QString& text) const { const QFont font {"sans-serif", pointSize}; // draw text painter.setFont(font); painter.setPen(QColor {"black"}); painter.drawText(0, 0, text); // draw horizontal advance painter.setPen(QPen {QColor {"red"}, 2}); painter.drawLine(0, 3, QFontMetricsF {font}.horizontalAdvance(text), 3); } void paintEvent(QPaintEvent *) override { QPainter painter {this}; const auto sysPtSize = QApplication::font().pointSize(); painter.translate(50, 50); this->_paintExample(painter, sysPtSize, "meow"); painter.translate(0, 50); this->_paintExample(painter, sysPtSize, "hello world!"); painter.translate(0, 50); this->_paintExample(painter, sysPtSize, "hello how are you today?"); painter.translate(0, 100); this->_paintExample(painter, -1, "meow"); painter.translate(0, 50); this->_paintExample(painter, -1, "hello world!"); painter.translate(0, 50); this->_paintExample(painter, -1, "hello how are you today?"); } };
从测试结果可见,使用点大小-1构造的字体,其文本宽度的红色标线明显长于使用系统默认点大小的情况,但实际绘制的文本视觉大小一致。
这属于Qt的已知行为,而非bug。原因在于:
- 当用
-1作为点大小构造QFont时,Qt内部尚未完成完整的**字体匹配(font matching)**流程,此时的QFont属于未完全解析的状态,QFontMetrics基于该字体计算出的度量数据存在偏差。 - 而
QApplication::font()获取的是已经经过系统上下文解析、完成字体匹配的实例,对应的度量数据是准确的。
如果需要获取系统默认字体的正确度量值,推荐直接使用QApplication::font();若必须手动构造QFont,可在构造后调用font.resolve(),或通过QWidget::font()间接获取经过解析的字体实例,再计算文本宽度。
内容的提问来源于stack exchange,提问作者eepp
相关产品推荐
相关产品推荐

