qt中文编码

前些日子,被编码折磨了一段时间,总结一下Qt中的编码。

【Qt 编码简单实验】

        首先,Qt中得QString 类对字符串进行了封装,其内部使用Unicode对传入的串进行编码。这样一来,QString就可以处理绝大多数的国际语言。将QString中的字符根据语言翻译的过程,也就是Qt 的Translater针对程序中使用含有的tr("XXXXX"),进行翻译的过程。由于QString的Unicode编码,和本地系统的编码不一定是一致的(比如系统采用的GB2312的编码)。这样的话,就不能直接使用类似QString str("汉字")这样的方法来存储本地的汉字,是有问题的。

    <系统是使用GB2312编码的>

    【试验1】

       QString str("汉字");

       std::cout << "Straight Output:" << str << endl; 

       std::cout << "Local Output:" << str.local8Bit() << endl;

       std::cout << "Unicode Output:" << str.unicode() << endl;

       结果如下:

       汉字       (正确)

       @#$%    (乱码)

       @#$%    (乱码)

    【试验2】

       QString str = QString::fromLocal8Bit("汉字");

       std::cout << "Straight Output:" << str << endl;

       std::cout << "Local Output:" << str.local8Bit() << endl;

       std::cout << "Unicode Output:" << str.unicode() << endl;      

       结果如下:      

       @#$%    (乱码)      

        汉字       (正确)

       @#$%    (乱码)

       首先说试验1,因为str采用Unicode编码,中文实际上没有经过任何的编码转换直接存到str中,所以存入的Unicode已经是错误的(GB编码的字符按照Unicode存的)。但是为什么第一个会正常显示呢?因为标准输入输出是不进行任何的编码解码工作的,字符串由本地系统读取时使用本地的字符集GB2312进行解码,因为存入的字符串“汉字”正好是GB2312编码的,正好得到了正确地结果!这有点负负得正的味道!QString只是充当了一个容器,里面存的是不正确的值。

    对于试验2来说,使用fromLocal8Bit()函数,实现了从本地字符集GB到Unicode的转换,所以存在QString中的字符串是经过转换的正确编码。输出的时候,要正确显示,只能是再转为本地的字符编码,也就是使用local8Bit()转换。由于存入QString的是正确的值,就可以进行包括国际化在内的许多工作!( 注意本地LANGUAGE环境变量!)

【Qt国际化的问题】

     在文本显示上,Qt 使用了Unicode 作为内部编码,为了程序的国际化,通常我们在文本显示的地方不直接输入本地字符,用英文代替,比如要编写一中文界面的 Qt 程序,应该在程序中使用英文,程序编写完成后,把文本提取出来翻译。对于需要翻译的地方,首先是在该文本处用tr()函数标识,同时制作出.qm信息文件,并在程序中加入QTranslator即可。

     比如我们在某一程序中有如下语句: setCaption(tr(“main window”)) 为了显示中文,有两种方法:

 方法一:

        1. 修改工程文件,加上TRANSLATIONS = xxx.ts

        2. lupdate 工程文件名

        3. 用linguist编辑刚生成的xxx.ts文件并保存

        4. lrelease 工程文件名 xxx.qm

        5. 在main.cpp中加入QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

        6. qApp->setFont(font1);

        7. QTranslator *translator = new QTranslator(0);

        8. translator->load("xxx.qm",".");

        9. qApp->installTranslator(translator);

方法二:

        1. findtr 文件名(通常为CPP文件) > xxx.po

        2. 编辑po文件,其中charset需由iso-8859-1改为GB2312,然后将“main window”翻译成“主窗口”

        3. msg2qm –scope zh_CN.GB2312 xxx.po xxx.qm

        4. 在main.cpp中加入QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

        5. qApp->setFont(font1);

        6. QTranslator *translator = new QTranslator(0);

        7. translator->load("xxx.qm",".");

        8. qApp->installTranslator(translator);

 方法三:

     有时我们只是提供给本地用户使用,无需国际化,QT提供这一支持,在QT中有许多本地字符集同unicode的转换引擎,他们皆为QTextCodec的派生类,如QGbkCodec、QJisCodec, QHebrewCodec等。如:

        QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

        qApp->setFont(font1);

        QString caption=“主窗口“;

        QTextCodec *gk_codec=QTextCodec::codecForName(“GBK”);

        setCaption(gk_codec->toUnicode(caption));  

       从上面可以看出,使用转换引擎可以轻松实现中文显示,简要步骤如下:

       1. 修改main.cpp文件,将字体改为unifont

              QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

              qApp->setFont(font1);

       2. 在想汉化的内的头文件中加入QTextCodec指针变量和转换函数QString mytr(char *)

       #include <qtextcodec.h>

       QTextCodec* gbk;

       QString mytr(const char *);

       3. 在想汉化的类的实现文件中,修改类构造函数,加入:

              gbk=QTextCodec::codecForName(“GBK”);

       4. 在想汉化的类的实现文件中,添加mytr函数代码

              QString Form1::mytr(const char* chars) {

               return gbk->toUnicode(chars,strlen(chars));

              }

       5. 在想汉化的类的实现文件中,用“mytr”替换“tr”

     注:如果将codec成员变量改成QTextCodec派生类变量,编译将通不过,比如将QTextCodec* gbk;改成QGbkCodec* gbk;编译将报告此处有语法错误。 

下面是相似的用法:

        1. 修改***.cpp文件,在顶部加入codec头文件

                 #include <qgbkcodec.h>

        2. 在***.h文件中,加入mytr()函数声明

                 QString mytr(char* buffer,int size);

        3. 在***.cpp文件中,加入mytr()定义

                 QString mytr(char* buffer,int size) {

                     QGbkCodec* gbk=QTextCodec::codeForName(“GBK”);

                     return gbk->toUnicode(buffer,size);

                  }

        4. 在需要显示中文的地方,使用mytr函数即可

        5. 修改main.cpp文件,将字体改为unifont

                     QFont font1(“unifont”,16,50,FALSE,QFont::Unicode);

                     qApp->setFont(font1);

    备注1:在翻译或转换之前必须将Unicode字体调入,否则显示不出中文,网上相关文章并未提及这一点,如果不显式装载该字体,系统默认的是Latin1,于是汉字显不出来。  

    备注2:在编译qt/embedded之前,必须修改qconfig-qpe.h配置文件的内容,将与TextCodec相关的宏定义给去掉,否则QTextCodec::codecForName(“GBK”)将返回NULL指针。

    备注3:使用findtr命令时可同时查找多个文件的tr(),并将查找结果都放入一个文件内,源文件以空格隔开即可,另外,生成的.po和.qm文件的文件名最好与工程文件名相同!  

    备注4:如果要显示繁体中文,则需要使用QTextCodec::codecForName(“big5”)。获取本地的使用语言,用QTextCodec::locale(),它返回Qstring变量,通常如果是中文本地的话,通常其值为zh_CN.GB2312和zh_TW.Big5,根据这个返回字符串,可以加载相应的codec。如果程序只支持一种编码,也可以直接把整个应用程序的编码设置为一个默认的编码标准,比如系统只需要显示中文和英文,则可以直接设置应用程序的默认编码标准是GBK,如下使用方法:

       qApp->setDefaultCodec( QTextCodec::codecForName("GBK") );

       QLabel *label = new QLabel( tr("中文标签") );

     备注5:如果使用本地的字符转换器,可以使用Qstring的静态函数Qstring::fromLocal8Bit(char* buffer,int size),将本地字符串转换成UNICODE字符串,不过要设置好LANGUAGE环境变量。

【QTOpia中文化 】

1) findtr 文件名 > xxx.po

2) 编辑xxx.po文件

3) msg2qm –scope zh_CN.GB2312 xxx.po xxx.qm

4) 拷贝可执行文件到QPEDIR/bin目录

5) 拷贝xxx.po和xxx.qm文件到QPEDIR/i18n/zh_CN目录

6) 进入QPEDIR/apps/Applications目录创建一新.desktop文件

7) iconv –f utf8 –t GB18030 xxx.desktop > xxx1.desktop

8) 编辑xxx1.desktop文件,主要是修改Exec、Icon、Name和Name[zh_CN]四项

9)  iconv –f GB18030 –t utf8 xxx1.desktop > xxx.desktop

10) rm –f  xxx1.desktop

11) qvfb –depth 16 &

12) cd $QPEDIR/bin

13) ./qpe  

     备注1:如果你的系统中有多个qtopia版本,要特别注意QTDIR、QPEDIR、LD_LIBRARY_PATH环境变量

 

     备注2:可按照此方法汉化qtopia自带的应用程序

     备注3:po文件是中间文件,程序真正需要的是qm文件。iconv是系统自带的内码转换工具,它能将utf8编码的文件转换成gb18030编码的文件,反之也能,转换这一步必不可少,因为desktop文件缺省是utf8编码的,而我们的redhat linux 7。3中文操作系统用的却是gb18030,所以在编辑器打开前需转换。

 

Linux教程-Linux下应用程序开发:QT国际化编程

    Qt 目前的版本(2.2.4)对国际化的支持已经相当完善。 在文本显示上,Qt 使用了Unicode 作为内部编码,可以同时支持多种编码。 为 Qt 增加一种编码的支持也比较方便,只要 增加该编码和Unicode的转换编码便可以了。 Qt 目前支持ISO标准编码ISO 8859-1, ISO 8859-2,ISO 8859-3,ISO 8859-4,ISO 8859-5,ISO 8859-7,ISO 8859-9,和 ISO 8859-15(对于阿拉伯语和希伯来语的支持正在开发之中),中文GBK/Big5,日文 eucJP/JIS/ShiftJIS,韩文eucKR,俄文KOI8-R。 当然也可以直接使用UTF8编码。
  
  Qt 使用了自己定义的Locale机制,在编码支持和信息文件(Message File)的翻译上弥补了目前Unix上所普遍采用Locale和gettext的不足之处。 Qt 的这种机制可以使 Qt 的同一组件(QWidget)上同时显示不同编码的文本。 比如,Qt 的标签上可以同时使用中文简体 和中文繁体文本。
  
  在文本输入上,Qt 采用了XIM(X Input Method)标准协议,可以直接使用XIM输入服务器。由于目前的绝大多数输入服务器都是针对单一语言的,所以在 Qt 的标准输入组件( QLineEdit,QMultiLineEdit)中的输入受到单一编码的限制,Qt 还不支持动态切换编码 输入的支持,这是它的不足之处。
  
  1. Qt 的文本显示
  使用 Qt 编写国际化的程序,最好不要在程序中直接使用特殊编码的文本。 比如要 编写一中文界面的 Qt 程序,应该在程序中使用英文,程序编写完成后,把文本提取 出来翻译。 这样,程序还可以根据Locale的不同,支持多种语言。 下面介绍如何在 Qt 程序中标注字符串,如何提取并翻译文本。
  
  像普通的国际化过程一样,Qt 使用了类似GNU gettext一样的函数 QObject::tr(),它 用于从Qt的信息文件 .qm 中取出信息,这些信息是经过 Qt 的工具处理的。 Qt在处理 编码时还使用了 QTranslator 类,可用于指定整个应用软件的 的信息文件。
  
  下面是一段使用了 QObject::tr()的代码,它建立了一个弹出菜单,菜单项是"Quit", 它被放置在菜单条上,在菜单条上显示的是标签"File"。
  
  QPopupMenu* popup;
  popup = new QPopupMenu( this );
  popup->insertItem( tr("&Quit"),qApp,SLOT(quit()) );
  menubar->insertItem( tr("&File"),popup );
  
  对于绝大多数情况,可以用上述方法处理。不过有时在定义某些变量中使用的字符 串,不能使用上述方法,但是为了让Qt提取并翻译该字符串,必须用某种方法标志出 来。Qt 定义了 QT_TR_NOOP() 和 QT_TRANSLATE_NOOP() 来标志它们。前者用于单个字符串,后者用于多个字符串。比如,
  
  static const char* strings = {
  QT_TR_NOOP( "Hello" ),
  QT_TR_NOOP( "World" )
  };
  
  有时需要使用printf/sprintf之类的函数动态生成字符串,比如,
  
  QStings s;
  s.sprintf( "Button %d",i );
  but->setText( s );
  
  对这种使用方式的国际化是使用 arg() 函数。
  
  QString s = tr( "Button %1" ).arg(i);
  but->setText( s );
  
  提取上述信息的方法是使用 Qt 提供的工具 findtr 命令:
  
  findtr .cpp > i18n.po
  
  它类似于GNU的 xgettext,上述文件的提取信息文件内包含,
  
  ....
  "Content-Type: text/plain; charset=iso-8859-1/n"
  
  #: i18n.cpp:34
  msgid "ExampleWidget::&File"
  msgstr ""
  ...
  
  接下来是文本翻译过程。 在Qt中翻译信息文件时应该注意以下事项: (1) 提取的信息文件的编码是iso-8859-1,在翻译成某种语言(编码)时应该 注意改动它的 字符集,比如对中文GB2312和Big5编码,应该是, "Content-Type: text/plain; charset=gb2312/n"或者"Content-Type: text/plain; charset=big5/n"。 (2) 提取的信息有一个范围,比如上面的文件指定的范围是 ExampleWidget, 在翻译 前应该把它去掉,变成 msgid "::&File"。(3) 被翻译的字符串可能含有加速键符号,如 "&File"中的"F",如果翻译成中文最好保留该信息,它可以翻译成 "文件(&F)"。
  
  对于翻译后的文件(比如上面的翻译文件存为 i18n_gb.po),必须使用 Qt 提供的 工具 msg2qm 把它转换为 .qm 文件才能使用,
  
  > msg2qm i18n_gb.po i18n_gb.qm
  
  它类似于GNU的 msgfmt 命令。翻译后的文件可以用Qt程序直接调用。
  
  QTranslator *translator = new QTranslator(0);
  translator->load("i18n_gb.qm",".");
  qApp->installTranslator(translator);
  
  此外,Qt 还提供了类似于 msgmerge 的工具 mergetr,它用于把新提取的信息 文件和已经翻译过的信息文件融合起来,在此不再赘述。
  
  在 Qt 中也可以直接使用 QTextCodec 来转换字符串的编码,这为在Qt下开发纯 中文软件带来了便利条件,不过这种方法不符和国际化/本地化的习惯,
  
  char *string = "中文和English混和字符串!"
  QTextCodec* gbk_codec = QTextCodec::codecByName("GBK");
  QString gbk_string = codec->toUnicode(string);
  QLabel *label = new QLabel(gbk_string);
  
  如果使程序只支持一种编码,也可以直接把整个应用程序的编码设置为GBK编码, 然后在字符串之前 加tr(QObject::tr),
  
  qApp->setDefaultCodec( QTextCodec::codecForName("GBK") );
  QLabel *label = new QLabel( tr("中文标签") );
  
  如果使Qt根据Locale的环境变量取得字符集,可以使用
  
  QString::fromLocal8Bit(str)。
  
  本节的例子请参见 qt-i18n-example.tar.gz
  
  2. Qt 的文本输入
  在输入方面,Qt 的输入条(QLineEdit)和编辑区(QMultiLineEdit)都支持 XIM,只要配合相应的输入服务器,便可以输入中文/日文/韩文。目前有许多支持XIM的软件,比如 中文: Chinput/xcin/rfinput/q9,日文: kinput2/skkinput,韩文: ami/hanIM。
  
  Qt程序的缺省输入风格是OverTheSpot风格,它也支持 OffTheSpot风格和 Root风格。 用户可以在起动程序时在命令行指定输入风格,比如对程序app,
  
  
  ./app -inputstyle overthespot  #缺省风格,光标跟随
  ./app -inputstyle offthespot
  ./app -inputstyle root
  
  经过 MiziLinux 补丁的Qt-2.2.0 支持 OnTheSpot 输入风格,并且把它作为 缺省的输 入风格。请参见 http://www.mizi.com/ko/kde/doc/onthespot/onthespot.html。
  
  Qt 中的任何一个 Widget 都可以接受输入,只要它可以有键盘聚焦(Keyboard Focus)。所以对特殊 Widget 的输入处理只需要截获键盘输入,获取从XIM服务器 来的字符串。 对于OverTheSport风格的支持,刷新XIM输入服务器的位置即可。
  
  3. Qt 的打印
  在打印方面,XWindow下的 Qt 生成PostScript并使用lpr打印。 它含有QPrinter类, 可以方便地支持输出页面的控制。 对于中文打印,必须修正PostScript文件的输出 部分。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值