QFont-使用外部字体文件的问题

博客讨论了在使用QFont进行序列化和反序列化时遇到的问题,特别是当用户在系统中安装新字体后,QPainter在重新加载工程时无法正确绘制文本。问题出在QFont的families属性在序列化时不完整,导致反序列化后的QFont在QPainter中无法正确填充families。解决方案是通过调用QFont::resolve()方法来确保所有属性完整。

        我们程序里面定义了某个结构体(这里简单描述为AStruct),AStruct包含了一个QFont 类型的成员变量:

struct AStruct {
    QFont ft;
};

        在具体业务上,AStruct中的QFont会被传递给QPainter去绘制文本。           

        保存工程/加载工程时时,会对AStruct对象进行序列化/反序列化操作:

        
struct AStruct {
    QFont ft;

    QString serialize() {
        QByteArray buf;
		QDataStream in(&buf, QIODevice::WriteOnly);
		in << font;
        return buf.toBase64();
    }

    void deserialize(const QString& d) {
        QByteArray buf = QByteArray::fromBase64(d.toLatin1());
        QDataStream out(&buf, QIODevice::ReadOnly);
		out >> font;
    }
};

        正常情况下,这套序列化/反序列化以及QPainter绘制文本都没有什么问题。但是客户在自己机器上安装了一个新的字体文件后(字体X),问题来了:

        在AStruct的编辑界面,用户在QFontComboBox里面选择了X字体,QPainter绘制正常。然后保存工程(序列化AStruct),再重新打开工程(反序列化AStruct),QPainter绘制异常,没有使用X字体来绘制文本。

        当时的第一反应就是可能序列化或者反序列出问题了,到底哪里出问题了呢?

       先排查序列化吧!  由于在第一次在编辑界面对AStruct设置为X字体后,QPainter绘制是正确的,说明那一次QPainter使用的字体是正确的,所以我把QPainter中的字体获取出来后,使用和AStruct中同样的方法对QFont进行序列化,得到一个序列化后的字符串,再和我工程里面存储的字符串进行比较,发现发现二者在后面一段有差异(标红的部分):

  工程文件里面的:      AAAAEnm5U2tOZmzViExOZnuAT1MACv////9ARAAAAAAAAP////8FAAEAMhAAAAEAAAAAAAAAAAAAAAAAA=

 从QPainter的QFont序列化出来的:

AAAAEnm5U2tOZmzViExOZnuAT1MACv////9ARAAAAAAAAP////8FAAEAMhAAAAEAAAAAAAAAAAAAAAAAAQAAABJ5uVNrTmZs1YhMTmZ7gE9TAAo=

想要知道这部分数据存的到底是什么,只能看QFont的的源码了:

QDataStream &operator<<(QDataStream &s, const QFont &font)
{
    if (s.version() == 1) {
        s << font.d->request.family.toLatin1();
    } else {
        s << font.d->request.family;
        if (s.version() >= QDataStream::Qt_5_4)
            s << font.d->request.styleName;
    }

    if (s.version() >= QDataStream::Qt_4_0) {
        // 4.0
        double pointSize = font.d->request.pointSize;
        qint32 pixelSize = font.d->re
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值