[PR]テレビ番組表
今夜の番組チェック


Qtで日本語を表示するには

 Qt 2.0以降では、文字列は内部的にはUnicodeで保持されます。 したがって、日本語の文字を表示する場合にはソースコードの日本語の文字列を、 プログラム中でUnicodeに変換する処理が必要です。 これは日本語対応パッチなどではなく、 全世界で使われる標準Qtでよく整備されているので、 特にコンパイル時に指定しなくても、 普通にQtをインストールしてあれば日本語を簡単に表示することができます
 日本語を表示する主な方法には

の3通りがあります。3番目がQtで推奨される完全な「国際化(I18N)プログラミング」 の作法にのっとった方法ですが、日本語のみターゲットの場合は若干荷が重いため、 もう少し簡単な、 2番目の「QTextCodecを使う方法」についてメモっておくことにします。

#include <stdio.h>
#include "qapplication.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qtextcodec.h"
#include "hello2.h"

HelloWidget::HelloWidget(QWidget* parent, char* name=0){
  QTextCodec* codec = QTextCodec::codecForName("eucJP");
  QFont* font = new QFont("fixed", 16, QFont::Normal);
  QLabel* laba = new QLabel(codec->toUnicode("波浪ワールド"), this);
  QPushButton* cmda = new QPushButton(this);
  QPushButton* cmde = new QPushButton(this);
  laba->setFont( * font);
  cmda->setText(codec->toUnicode("警報"));
  cmda->setFont( * font);
  cmde->setText(codec->toUnicode("避難"));
  cmde->setFont( * font);
  laba->move(30, 20);
  laba->setMinimumSize(laba->sizeHint());
  cmda->move(30,  60);
  cmde->move(170, 60);

  QObject::connect(cmda, SIGNAL(clicked()), this, SLOT(buttonClicked()));
  QObject::connect(cmde, SIGNAL(clicked()), this, SLOT(close()));

  this->resize(300, 100);
  this->setCaption("hello world");
}

void HelloWidget::buttonClicked(void){
  fprintf(stdout, "Button Clicked!\n");
}

int main(int argc, char* argv[]){
  QApplication* a = new QApplication(argc, argv);
  QTextCodec* codec = QTextCodec::codecForName("eucJP");
  a->setDefaultCodec(codec);

  HelloWidget* my = new HelloWidget(NULL);
  a->setMainWidget(my);
  my->show();
  return a->exec();
}
/* end. */

これを「hello2.cpp」と名付けます。 ポイントは

QTextCodec* codec = QTextCodec::codecForName("eucJP");

このようにQTextCodec::codecForNameメソッドで使いたい (=ソースプログラムを書くのに使った)文字コード、 ここでは「eucJP」(*1)を指定します。 あとはそのインスタンスの toUnicode() メソッドを使えばプログラム中に書いた日本語の文字列が表示できます。
 で、その日本語フォントですが、 Xウィンドウシステム標準の 「-misc-fixed-medium-r-normal-うんたら-うんたら-...」 という長々とした指定は不要で、Tcl/TkやJavaと同じように、 フォントのファミリー、サイズ、スタイル(太字、イタリック)の組を指定するだけでOKです。とても簡単ですね。

  QFont* font = new QFont("fixed", 16, QFont::Normal);
  laba->setFont( * font);

(*1)シフトJISコードの場合は「SJIS」です。

 次に上のソースコードがインクルードしているヘッダファイルを下のように作り、 「hello2.h」と名付けます。

#include "qwidget.h"
class HelloWidget : public QWidget {
Q_OBJECT
public:
  HelloWidget(QWidget* parent, char* name=0);
public slots:
  void buttonClicked(void);
};

 で、先述の通り、mocを使ったりするためコンパイルが若干面倒なため、 Makefileも作ります。

CC	= gcc
CXX	= g++
QTDIR	= /usr/local/qt
MOC	= ${QTDIR}/bin/moc
CFLAGS	= -I$(QTDIR)/include -g -O
LDFLAGS = -L$(QTDIR)/lib
LIBS	= -lqt
.SUFFIXES: .cpp .cxx .cc .C .c
.cpp.o:
	$(CXX) -c $(CFLAGS) -o $@ $<

SRCS2	= hello2.cpp moc_hello2.cpp
OBJS2	= hello2.o   moc_hello2.o

hello2: $(SRCS2) $(OBJS2)
	$(CXX) -o $@ $(LDFLAGS) $(OBJS2) $(LIBS)
moc_hello2.cpp : hello2.h
	$(MOC) -o $@ $<
# end.

あとは「make」でコンパイルできるはずです。 うまくコンパイルできたら、実行してみましょう。

SEREEN=qthelloj.png

 ちなみに、Qtアプリケーションにデフォルトのcodecを指定しておくこともできます。 日本語文字列をリテラル直書きで使うことが多い場合には、こちらの方が書きやすいでしょう。

#include <stdio.h>
#include "qapplication.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qtextcodec.h"
#include "hello2.h"

HelloWidget::HelloWidget(QWidget* parent, char* name=0){
  QFont* font = new QFont("fixed", 16, QFont::Normal);
  QLabel* laba = new QLabel(tr("波浪ワールド"), this);
  QPushButton* cmda = new QPushButton(this);
  QPushButton* cmde = new QPushButton(this);
  laba->setFont( * font);
  cmda->setText(tr("警報"));
  cmda->setFont( * font);
  cmde->setText(tr("避難"));
  cmde->setFont( * font);
  laba->move(30, 20);
  laba->setMinimumSize(laba->sizeHint());
  cmda->move(30,  60);
  cmde->move(170, 60);

  QObject::connect(cmda, SIGNAL(clicked()), this, SLOT(buttonClicked()));
  QObject::connect(cmde, SIGNAL(clicked()), this, SLOT(close()));

  this->resize(300, 100);
  this->setCaption("hello world");
}

void HelloWidget::buttonClicked(void){
  fprintf(stdout, "Button Clicked!\n");
}

int main(int argc, char* argv[]){
  QApplication* a = new QApplication(argc, argv);
  QTextCodec* codec = QTextCodec::codecForName("eucJP");
  a->setDefaultCodec(codec);

  HelloWidget* my = new HelloWidget(NULL);
  a->setMainWidget(my);
  my->show();
  return a->exec();
}
/* end. */

 アプリケーションにデフォルトのcodecを設定するのは、 この2行だけで行えます。

  QTextCodec* codec = QTextCodec::codecForName("eucJP");
  a->setDefaultCodec(codec);

あとは、表示するのに使う日本語の文字列を全て QObject::tr()メソッドに渡すだけでUnicodeに変換できます。 QWidgetなどほとんどのQtウィジェットクラスはQObjectクラスを継承しているので、 普通は単に「tr」と書くだけでOKです。


Qtで日本語を入力するには

 はい、日本語の表示ができたら、そうそう、日本語の入力もできて、 なおかつプログラム内でちゃんと日本語として扱われるかどうかが気になる気になる木ですが、 気をモムことなかれ、 Xウィンドウシステム上では日本語かな漢字入力システム 「うんぬ」や「かんな」と代表的な日本語かな漢字入力フロントエンド「kinput2」 を使って、なんと完璧に日本語の入力ができるようになっています。 これも日本語パッチなどではなく、全世界に一次配布される QtをインストールするだけでOK。さああなたも使うしか。

 …実験台として、ラインエディット(QLineEdit)ウィジェットに日本語を入力してみます。 まずヘッダファイルを「linee.h」とか適当な名前で下のように作ります。

/* linee.h */
#include "qwidget.h"
#include "qlineedit.h"
class HelloWidget : public QWidget {
Q_OBJECT
public:
  HelloWidget(QWidget* parent, char* name=0);
public slots:
  void buttonClicked(void);
protected:
  QLineEdit* leda;
};
/* end. */

次に本体のソースプログラム「linee.cpp」です。

/* linee.cpp */
#include >stdio.h<
#include "qapplication.h"
#include "qlabel.h"
#include "qpushbutton.h"
#include "qtextcodec.h"
#include "linee.h"
HelloWidget::HelloWidget(QWidget* parent, char* name=0){
  QFont* font = new QFont("fixed", 16, QFont::Normal);
  QLabel* laba = new QLabel(tr("文字列を入力してチョ:"), this);
  this->leda = new QLineEdit(this);
  QPushButton* cmde = new QPushButton(this);
  laba->setFont( * font);
  cmde->setText(tr("終了"));
  cmde->setFont( * font);
  laba->move(10, 20);
  laba->setMinimumSize(laba->sizeHint());
  leda->setGeometry(10, 50, 150, 24);
  cmde->move(170, 80);
  QObject::connect(cmde, SIGNAL(clicked()), this, SLOT(buttonClicked()));
  this->resize(300, 130);
  this->setCaption("lineedit example");
}

void HelloWidget::buttonClicked(void){
  QString s = this->leda->text();
  fprintf(stdout, "Accepted Text: %s\n", (char* )(s.local8Bit()));
  this->close();
}

int main(int argc, char* argv[]){
  QApplication* a = new QApplication(argc, argv);
  QTextCodec* codec = QTextCodec::codecForName("eucJP");
  a->setDefaultCodec(codec);
  HelloWidget* my = new HelloWidget(NULL);
  a->setMainWidget(my);
  my->show();
  return a->exec();
}
/* end. */

日本語テキストの表示については、先述の QApplication::setDefaultCodecQObject::trを使っているので、 再度紹介の必要はないでしょう。 で、日本語をQLineEditウィジェットに入力できるようにする処理は、 ありません。はにゃ?つまり、何もしなくても、「kinput2」さえ上げておけば、 アルファベットと同じように日本語も入力することができ、 なおかつ入力した文字は日本語でちゃんと表示されます。

 唯一問題になるのが、Qtでは(何度も先述した通り) 内部文字列がUnicodeなので、ファイルに書き出すなどの場合日本語EUCやシフトJISなどポピュラーな日本語文字コードに変換する必要があることです。 この変換ルーチンもQtに内蔵されていて、 それを使っているのが上のこの部分です。

  QString s = this->leda->text();
  fprintf(stdout, "Accepted Text: %s\n", (char* )(s.local8Bit()));

QLineEditウィジェットに入力された内容は、text() メソッドでQString型のオブジェクトとして返されるので、 そのメソッドlocal8Bit()で現在環境変数LANGで設定されている内容に合わせて (LANGがja_JP.eucJPなら日本語EUC、というように)変換されます。 これをファイルに書き出したりすればテキストエディタなどで見ることができます。

 では、コンパイルしてみます。Makefileはこんな感じです。

CC	= gcc
CXX	= g++
QTDIR	= /usr/local/qt
MOC	= ${QTDIR}/bin/moc
CFLAGS	= -I$(QTDIR)/include -g -O
LDFLAGS = -L$(QTDIR)/lib
LIBS	= -lqt
.SUFFIXES: .cpp .cxx .cc .C .c
.cpp.o:
	$(CXX) -c $(CFLAGS) -o $@ $<
linee: linee.o moc_linee.o
	$(CXX) -o $@ $(LDFLAGS) linee.o moc_linee.o $(LIBS)
moc_linee.cpp : linee.h
	$(MOC) -o $@ $<
# end.

 うまくコンパイルできたら、「うんぬ」か「かんな」と「kinput2」 をバックグラウンドで走らせておき、 このアプリケーションを実行します。

スクリーンショット

ちょっとフォントがフニャっていますが、 ちゃんとした固定長の綺麗なフォントも出すことができます。 いずれ差し替えます、ということで。

セクションのサブメニューに戻る
(first uploaded 2000/08/08 last updated 2002/03/21)