Qt编码问题(2)

本节讲述Qt乱码问题
在《Qt编码问题(1)》一文中已经讲过一些编码相关问题,下面进行一些关于乱码的解决。
先看例子:
QString s1 = "我是中文";
QString s2("我是中文");
QString s3;s3 = "我是中文";

这三个例子都是将字节流(char*)内容赋值或者传递给字符流(QString),系统(包括我们)知道Qt中字符流使用的是unicode字符集,却不知道字节流使用的是何种编码方式,(unicode有多重编码存储方式,utf-8就是其中一种)所以Qt默认会用latin1编码来解释字符流(用拉丁1编码方式来解释中文,肯定是乱码),再传给字符流对象,这样,乱码就出现了.我们可以总结出以下3点:
1.当将字节流串赋值到QString时,我们需要告诉它我们的字节流采用的何种编码(gbk?、utf-8?)
2.究竟何种编码主要取决于我们的源代码文件的编码(windows上一般是gbk,其他平台一般utf-8)
3.如果不指定编码,s1,s2,s3将全部都是(国内大多数人所称的)乱码。因为QString将这些const char *按照latin1来解释的,而不是用户期待的gbk或utf8。
所以我们需要在赋值前制定以下语句中的一条:

QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"))

来告诉QString用什么编码来解释字节流;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
本节讲述tr()问题
tr()的作用是为了实现代码的国际化,说白了就是一个翻译。
tr(A国文字);如果程序被提供了A国文字到B国文字的翻译包,那么使用tr()的单位得到的将是对应的B国文字,举个例子:

QString text1 = QObject::tr("hello");
 QString text2 = QString("hello");
如果你为这个程序提供了英文到中文翻译包(其中hello被翻译成中文"你好"),那么text1的内容将是中文"你好";如果你为程序提供且使用日文翻译包,那么text1的内容将是日文。但是text2却不会改变,一直是“hello”这个英文单词。

tr是经过多级函数调用才实现了翻译操作,是有代价的,所以不该用的时候最好不要用。

与QString("我是中文")完全一样,你必须告诉tr这个字节流是何种编码?你不告诉它,它就用latin1。于是所谓的乱码问题就出来了(也许纯英文的不会出现乱码问题)。
比如tr("我是中文");
你需要告诉tr你写的这几个汉字在磁盘中保存的是何种编码,这正是

QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
所做的。这两个选择的原则,由于和前文完全一样,此处也不再重复。

其实真正实现翻译操作的函数并不是tr(),这一点在下一节有说明。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
这一节我是从其他人博客上直接复制的,还没怎么看,后面会提供参考链接
QCoreApplication::translate
我们知道tr是用于实现程序的国际化(或者说多语言翻译),看Qt相关资料的话,我们知道实现该功能的还有下面这个函数:

QString QCoreApplication::translate ( const char * context, const char * sourceText, const char * disambiguation, Encoding encoding, int n )
其实,这个才是真正进行翻译操作的函数,前面我们提到的tr最终是通过调用该函数来实现翻译功能的(稍后我们会看tr是如何调用translate的)。

对tr和这个函数,manual中都有比较详尽的解释。我们这儿简单看一下它的这几个参数:

context 上下文,一般就是需要翻译的字符串所在的类的名字
sourceText 需要翻译的字符串。(我们关注的编码其实就是它的编码)
disambiguation 消除歧义用的。(比如我们的类内出现两处"close",一处含义是关闭,另一处含义是亲密的。显然需要让翻译人员知道这点区别)
encoding 指定编码。它有两个值
CodecForTr 使用setCodecForTr()设置的编码来解释 sourceText

UnicodeUTF8 使用utf8编码来解释 sourceText
其实这两个分别对应tr和trUtf8
n 处理单复数(对中文来说,不存在这个问题)
tr与translate
这两个函数的说明,一个在QObject的manual,另一个在QCoreApplication的manual中。

介绍一下tr与translate的关系。前面提到了,tr调用的是translate。如果仅仅这样一说,没有证据,还真难以让大家相信。好吧,继续

tr 在何处定义
你可能说:这不废话吗,manual中写得明白的,它是QObject的静态成员函数。而且还有源码为证:

//来自 src/corelib/kernel/qobject.h #ifdef qdoc static QString tr(const char *sourceText, const char *comment = 0, int n = -1);static QString trUtf8(const char *sourceText, const char *comment = 0, int n = -1);#endif

嘿嘿,差点就被骗了,发现没:它们被预处理语句包住了。

这说明了什么呢?说明了这段代码仅仅是用来生成Qt那漂亮的文档的(qdoc3从代码中抽取信息,生成一系列的html格式的manual)。

啊,也就是说,这是假的。那么真正的定义呢??在一个大家都很熟悉的地方,猜猜看?

这就是

Q_OBJECT
该宏的定义在src/corelib/kernel/qobjectdefs.h中

#define Q_OBJECT \ public: \ Q_OBJECT_CHECK \ static const QMetaObject staticMetaObject; \ Q_OBJECT_GETSTATICMETAOBJECT \ virtual const QMetaObject *metaObject() const; \ virtual void *qt_metacast(const char *); \ QT_TR_FUNCTIONS \ virtual int qt_metacall(QMetaObject::Call, int, void **); \ private:


其中的宏QT_TR_FUNCTIONS

#  define QT_TR_FUNCTIONS \ static inline QString tr(const char *s, const char *c = 0) \ { return staticMetaObject.tr(s, c); } \ static inline QString trUtf8(const char *s, const char *c = 0) \ { return staticMetaObject.trUtf8(s, c); } \ static inline QString tr(const char *s, const char *c, int n) \ { return staticMetaObject.tr(s, c, n); } \ static inline QString trUtf8(const char *s, const char *c, int n) \ { return staticMetaObject.trUtf8(s, c, n); }
现在看到:tr调用的是 staticMetaObject对象的tr函数,staticMetaObject 的定义在moc生成的 xxx.moc 或 moc_xxx.cpp 文件内(你随时可以验证的)。

staticMetaObject 是一个 QMetaObject 类的实例,我们继续看一下该类的源码:

/*! \internal */ QString QMetaObject::tr(const char *s, const char *c) const { return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr); } /*! \internal */ QString QMetaObject::trUtf8(const char *s, const char *c) const {     return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8); }
至此,我们应该都看清楚了。我们的 Q_OBJECT 宏展开后为生成 tr ,tr调用QCoreApplication的translate函数。而该函数需要指定编码。

From:http://hi.baidu.com/cyclone/blog/item/aa56e5dd1a79f7e176c638be.html

 


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值