我们程序里面定义了某个结构体(这里简单描述为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

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

被折叠的 条评论
为什么被折叠?



