linux上でGraphicsを使用した部分で,InternalErrorが発生する問題

Graphicsを使用して,グラフを描く処理が入っているソースをlinux上で動かそうとしたところ,以下のようなエラーが発生.

java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.
sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
sun.awt.X11GraphicsEnvironment.(X11GraphicsEnvironment.java:134)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:141)
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:62)
java.awt.image.BufferedImage.createGraphics(BufferedImage.java:1041)
(以下略)

回避方法としては,実行時のオプションとして,「-Djava.awt.headless=true」を追加する.

例:
# javac SampleIMGCreate.java
# java -Djava.awt.headless=true SampleIMGCreate

などと書いたものの,単体駆動なんてまずしないだろうから,Tomcatサーバ上で動かしている場合は,Tomcat実行ユーザの環境変数にこのオプションを追加し,Tomcatを再起動すれば良い.

# export CATALINA_OPTS="-Djava.awt.headless=true"

参考URL:http://java.sun.com/j2se/1.4.2/docs/guide/awt/AWTChanges.html#headless

linux上でjava.awt.Graphicsを使って表示した日本語が文字化け

先の対処で実行時エラーは解消して,絵が表示されるようになったものの,今度は日本語部分が文字化け.(Windows環境下では問題なかったのに…)
g.drawString()とかで表示する日本語部分が→「□□□」みたいな感じに化けてしまう.
原因は,linuxデフォルトのフォントが日本語に対応していないからというもの.
よーするに,Graphicsオブジェクトに対して,どのFontを使うかを明示的に指定しないとダメなのでした.(WindowsではたまたまデフォルトのFontが日本語に対応していただけのハナシ)
指定しない場合はその実行環境デフォルトのFontが採用されてしまう.

というわけで,

  1. その実行環境で対応しているFont一覧を取得
  2. それらのうち日本語表示に対応しているものを見つける
  3. 日本語に対応したFontをGraphicsオブジェクトに指定する

という手順を踏まねばならない.
サンプルは以下のとおり,


(前略)
//インストールされている全てのFontを取得
Font[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();

//その中から日本語に対応したものを抽出
ArrayList fontList = new ArrayList();
for(int i = 0; i < fonts.length; i++){
if(fonts[i].canDisplay('日')){
fontList.add(fonts[i]);
}
}

//抽出したFontの中に、MS Gothic(Windowsならたいていあるはず)が入っていればそれを採用,
//なければ「Kochi Gothic」(linuxに入っている)を採用
//それもなければ,何でもいいから日本語に対応しているFontを採用

Iterator itr = fontList.iterator();
while(itr.hasNext()){
Font f = (Font)itr.next();
if(f.getName().equals("MS Gothic")){
g.setFont(new Font(f.getName(), Font.PLAIN, 12));
break;
} else if (f.getName().equals("Kochi Gothic")){
g.setFont(new Font(f.getName(), Font.PLAIN, 12));
break;
} else {
g.setFont(new Font(f.getName(), Font.PLAIN, 12));
}
}
(後略)

これはあくまでもサンプルで,これやるとちょっと処理時間がかかる….

続きを読む