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 �Cscope 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 �Cscope 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 �Cf utf8 �Ct GB18030 xxx.desktop > xxx1.desktop
8) 编辑 xxx1.desktop 文件,主要是修改 Exec Icon Name Name[zh_CN] 四项
9)   iconv �Cf GB18030 �Ct utf8 xxx1.desktop > xxx.desktop
10) rm �Cf xxx1.desktop
11) qvfb �Cdepth 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 ,所以在编辑器打开前需转换。
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文件的输出 部分。

你可能感兴趣的:(职场,中文,qt,休闲)