浅谈Linux 下的中文程序开发
[日期:2007-08-05]
来源:Linux公社
作者:Linuxidc
[字体:大 中 小]
这 里我们看到,同样的, 把 input 中我们输入的 string 扔给 string. 下面就用到了 QTextCodec 了.我们可以把 QTextCodec *codec=QTextCodec::codecForName("big5"); 写成两行,这样比较方便看:
代码:
QTextCodec *codec;
codec=QTextCodec::codecForName("big5");
第一行是通过 QTextCodec 建立 codec 第二行呢,告诉 QT 我们的 codec 是用 big5 编码的. (简体中文就要用 gb2312)
最 后,我们通过 codec->formUnicode(string) 把 Unicode 转换成我们需要用的 big5 码. ( QT default 全部是用 Unicode,这也就是为什么开始的时侯,如果我们没有通过 QTextCodec 转码,看到的中文都是 ?? 了.因为 Unicode 的标准就是不认得的 code 一律用 ?? 来表示)最后我们定义一个 QCString chinese_string,
代码:
QCString chinese_string=codec->fromUnicode(string);
而 chinese_string就是已经被 codec 转码过的 big5 code 的了. codec->fromUnicode(string) 这里是做转码的动作.
现在重新 make 所 build 出来的 chinese 就已经具备了最基本的中文程序的要求了.现在在输入中文到程序中,您就可以在 X 终端模拟中看到中文了.
那么这个程序已经具备了中文处理能力,为什么还被叫做最基本的呢中文处理呢?因为我们的程序目前并不会判断 locale, 而自动设定相应的编码.现在我们把这个 chinese 的程序作成一个相对完整的中文程序.
QTextCodec 中还给我们提供了一个读取当然于言环境的 function 叫做 locale. QTextCodec::locale() 就会返回当前使用者的 locale. 现在让我们来看看一个相对完整的中文程序:
Tips: 这个程序中对 locale 名称的定义 是按照 RedHat 7.3 中对中文 locale 的定义为标准的,也就是说: 繁体中文 : zh_TW.Big5 简体中文 : zh_CN.GB2312
代码:
/* chinese.h */
#include
#include
#include
#include
#include
class Chinese: public QWidget
{
Q_OBJECT
public:
Chinese();
private:
QLabel *label;
QLineEdit *input;
QString locale;
private slots:
void display();
};
我们这里加入了一个新的 QString locale, 用来做 locale 的判断.
代码:
/* chinese.cpp */
#include "chinese.moc"
#include
#include
Chinese::Chinese()
{
resize(200,100);
QTranslator translator(this);
locale=QTextCodec::locale();
translator.load("chinese."+locale, ".");
qApp->installTranslator(&translator);
label=new QLabel(tr( "Input Line:"), this);
label->setGeometry(10,10,90,30);
input=new QLineEdit(this);
input->setGeometry(10, 40, 180, 30);
input->setFocus();
connect(input, SIGNAL(returnPressed()), this, SLOT(display()));
}
void Chinese::display()
{
QString string;
string=input->text();
QTextCodec *codec;
if (locale == "zh_TW.Big5")
codec=QTextCodec::codecForName("big5");
if (locale == "zh_CN.GB2312")
codec=QTextCodec::codecForName("gb2312");
QCString encoded_string=codec->fromUnicode(string);
cout< }
在 chinese.cpp 里面, Chinese::Chinese 我们加入 locale 的判断. 从而自动加载相应的 .qm 文件.
locale=QTextCodec::locale() 就把 QTextCodec 返回的值,也就是当前使用的 locale 传给了 locale. (locale 是一个 QString)然后我们用 translator.load("chinese."+locale, "."); 实际上就是说 chinese.+当然 locale (zh_TW.Big5 或者 zh_CN.GB2312)也就是说,最后我们加载的 locale 是 chinese.zh_TW.Big5 或者是 chinese.zh_CN.GB2312. 这样只要对应不同的 locale 环境翻译不同的 .po 然后制作成基于 locale 名称的 qm, QT 就可以帮我们自动判断在哪个locale 要加载那个文件了. (chinese.zh_TW.Big5.qm 或者 chinese.zh_CN.GB2312.qm)
Tips: QT 在载入 .qm 文件的时侯,如果该文件不存在.那么 就会用程序中的语言来显示.所以不需要为了程序是否 可以找到该 .qm 文件而担心.(不用去写 这方面的 error handle)
而 在 void Chinese::display() 中,我们也做一个自动的判断,用来判断使用者是在哪个中文环境中输入中文的. 如果是 zh_TW.Big5 我们就把转码设定为 big5, 如果是 GB2312 就设定为 gb2312. 而如果是其它的,就忽略不管了.
同时在修改一下我们的 Makefile
代码:
INCL= -I$(QTDIR)/include -I/usr/include/kde
CFLAGS= -pipe -O2 -fno-strength-reduce
LFLAGS= -L$(QTDIR)/lib -L$(KDEDIR)/lib -L/usr/X11R6/lib
LIBS= -lkdecore -lkdeui -lqt -lX11 -lXext -ldl
CC=g++
MOC=moc
chinese: chinese.moc chinese.o main.o
$(CC) $(LFLAGS) -o chinese chinese.o main.o $(LIBS)
chinese.moc: chinese.h
$(MOC) chinese.h -o chinese.moc
main.o: main.cpp
chinese.o: chinese.cpp
po:
findtr3 chinese.cpp > chinese.zh_TW.Big5.po
findtr3 chinese.cpp > chinese.zh_CN.GB2312.po
qm:
msg2qm2 chinese.zh_TW.Big5.po chinese.zh_TW.Big5.qm
msg2qm2 chinese.zh_CN.GB2312.po chinese.zh_CN.GB2312.qm
clean:
rm -f *.o
rm -f *.bak
rm -f *.moc
rm -f chinese
.SUFFIXES: .cpp .h
.cpp.o:
$(CC) -c $(CFLAGS) $(INCL) -o $@ $<
在 Makefile 中加入 po 和 qm. 这样我们用 make po 就会产生 chinese.zh_TW.Big5.po 和 chinese.zh_CN.GB2312.po 了.把这两个 po 翻译好以后.用 make qm 就会做出 chinese.zh_TW.Big5.qm 和 chinese.zh_CN.GB2312.qm 这两个 qm 文件.现在试试看.在简体或者繁体的 X 终端模拟环境下.我们的程序会自动的显示相应的翻译信息.也会自动接受相应 locale 下面的中文输入法了.
GTK+
在 Linux 下面,还有一个常用的 GUI 环境开发语言.就是GTK+ 了. 大家都知道, gnome 这套桌面环境就是由 GTK+ 开发出来的. 现在我们来看看 GTK+ 如何处理中文.
Tips: 这里我们以 GTK 1.x 为例. (因为 GTK 2.x 目前 还不算是非常的稳定)
Tips: 如果您希望在自己的计算机中编译本文中的范例, 您需要安装 gcc, gtk+, gtk+-devel, make , gettext, 这些套件.
首先我们先来用 GTK 写一个跟前面 QT 中的那个程序功能完全一样的程序.
代码:
/* chinese.c */
#include
#include
void display (GtkWidget *widget, GtkWidget * entry)
{
const gchar *entry_text;
entry_text=gtk_entry_get_text( GTK_ENTRY (entry));
printf ("%s\n", entry_text);
}
void destroy(GtkWidget *widget, gpointer *data)
{
gtk_main_quit();
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *entry;
GtkWidget *label;
gtk_init(&argc, &argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy),NULL);
gtk_container_border_width(GTK_CONTAINER(window),10);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
gtk_widget_show(vbox);
label= gtk_label_new("Input Line");
gtk_box_pack_start(GTK_BOX (vbox), label, TRUE, TRUE, 0);
gtk_widget_show(label);
entry= gtk_entry_new();
gtk_signal_connect(GTK_OBJECT(entry), "activate",
GTK_SIGNAL_FUNC(display), entry);
gtk_box_pack_start(GTK_BOX (vbox), entry, TRUE, TRUE, 0);
gtk_widget_show(entry);
gtk_widget_show(window);
gtk_main();
return 0;
}
里 面的 void display() 就相当于前面 QT 中的 void Chinese::display() 是用来把我们输入的东西显示在您的 X 终端模拟上面的. 我们首先通过 gchar 来定义一个 entry_text, 然后用 gtk_entry_get_text(GTK_ENTRY())来把我们输入的东西抓出来,放到 entry_text 中去.再用 C 语言中的 printf 把它显示在我们的 X 终端模拟上面.
void destory() 告诉程序,如果收到程序结束的信号,(例如你按了窗口中的那个小 X )那么就代表程序结束. 退出 gtk 的 main loop.
我 们的 main 程序中. 定先义了 window, vbox, entry, label 这己个物件.这里面, window, 就是我们看到的主窗口. vbox 是 gtk+ 中一种用来排列对象的东西. entry 是给我们输入用的(QT 中的 QLineEdit)lable 是作为显示一个信息而用的. (QT 中的 QLabel)
gtk_init() 帮我们初始化 gtk.
window=gtk_window_new 就通过 gtk_window_new 把 window 定一为一个新的窗口.也就是我们的主窗口了. GTK_WINDOW_TOPLEVEL 则告诉程序,我们的这个主窗口显示的时侯,是在最上面的. ( TOPLEVEL)
gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy),NULL); 这一行,首先我们连接一个 gtk 的信号, 对象是在 window 上面. 信号的内容为 destroy, 当收到这个信号以后,用 GTK_SIGNAL_FUNC() 去呼叫 destroy() 这个 function . 传给 function 的值为 NULL. 也就是说,当我们的主窗口 window 接收到遗个 destroy 的信号的时侯, 去呼叫 destroy() 结束 gtk 程序. 这里的 destroy 信号就是代表你关闭主窗口的意思. 在 gtk 中,当你关闭了一个窗口, gtk 就会帮你送出一个 destroy 的信号.