You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:47:28