HOW TO ARTICLES
Beeswax - Is it worth it?
Lore vel iriustie doluptat utpat do conullam, volorpero dip ex eugiat.
How to clean a candle
Lorper si tion heniam eu facilismod tetuercipsum ilit vel dolesto conulputatet.
Lavender &ハSage Candles
Ut wis autpat ad min henim quamcommolenim nibh ex et iuscipsustrud dit aut in voloboreet dit lorperit praesent ullan exerat, velessi.
|
ここの内容ぜんぶWikiに書き換え中
オタク
java skin ジャヴァ スキン
gui swing かっこよく
ルックアンドフィール
setLookAndFeel
setDefaultLookAndFeelDecorated
LookAndFeel
look and feel
■java gui ルック&フィールをかっこよくする。
何かと仕事のツール作成などでSwingを使う事があるけど、いつもいつもいつもいつも
思ってた事だけど、JavaのGUIはかっこわるい!時々JavaGUIそのまんまの製品があるが、
Javaは大好きだけどあのGUIだとまずその時点で評価超ダウンです。そうです面食いです。
そんなこんなでいいもの見つけました。
ThemapackというSkinなような概念でJava物をかっこよくしてくれます。
もちろんフリー。
HP:
http://www.l2fprod.com/
Skin拾える所:
http://javootoo.l2fprod.com/plaf/skinlf/index.php
■評価
・ちょっとJavaっぽくないかっこわるい所がある。
・でもとってもかわいいSkinがいっぱいあるから許す。
■一番融通の利くんじゃないかな〜という書き方例
サンプルsrcディレクトリ構成:
src/
|
|--skinlf/
|
|--Frame1.java(JFrame実装)
|
|--themepack/(スキン用ディレクトリ)
|
|--themepack/(デフォルトスキンディレクトリみたいな)
|
|--gtk/
|
|--icons/
|
|--kde/
|
|--skinlf-themepack.xml
コンパイル後想定構成:
build/
|
|--skinlf/
|
|--Frame1.class
|
|--themepack/
|
|--themepack.zip
※実行時にはskinlf.jarをクラスパスに
skinlf/themepackがzipされてthemepack.zipになります。
てかantでzipするからskinlf/themepackディレクトリの位置は
あからさまに無駄だけどねぇ〜。まぁ適当に。
要約:
import com.l2fprod.gui.plaf.skin.*;
...
public static void main(String[] args) throws Exception{
Skin skin = SkinLookAndFeel.loadThemePack(Frame1.class.getResource("/themepack/themepack.zip"));
SkinLookAndFeel.setSkin(skin);
UIManager.setLookAndFeel(new SkinLookAndFeel());
JFrame.setDefaultLookAndFeelDecorated(true);
...
SkinLookAndFeel.loadThemePackはthrows Exceptionです。かっこわるい!
Exceptionのはき方は威風堂々とNullPointerExceptionだしまくりです。
例えば画像が足りなかった時などに原因追求相当厳しいね。
sample code:
------------- sample code サンプルコード -------------
package skinlf;
import javax.swing.*;
import java.awt.*;
import com.l2fprod.gui.plaf.skin.*;
public class Frame1 extends JFrame {
JPanel jPanel1 = new JPanel();
JButton jButton1 = new JButton();
JRadioButton jRadioButton1 = new JRadioButton();
JToggleButton jToggleButton1 = new JToggleButton();
JCheckBox jCheckBox1 = new JCheckBox();
JTextField jTextField1 = new JTextField();
JList jList1 = new JList();
JProgressBar jProgressBar1 = new JProgressBar();
JSlider jSlider1 = new JSlider();
public Frame1() {
try {
jbInit();
}
catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception{
Skin skin = SkinLookAndFeel.loadThemePack(Frame1.class.getResource("/themepack/themepack.zip"));
SkinLookAndFeel.setSkin(skin);
UIManager.setLookAndFeel(new SkinLookAndFeel());
JFrame.setDefaultLookAndFeelDecorated(true);
Frame1 frame1 = new Frame1();
frame1.setSize(640,480);
frame1.show();
}
private void jbInit() throws Exception {
jButton1.setText("jButton1");
jRadioButton1.setText("jRadioButton1");
jToggleButton1.setText("jToggleButton1");
jCheckBox1.setText("jCheckBox1");
jTextField1.setText("jTextField1");
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.getContentPane().add(jPanel1, BorderLayout.CENTER);
jPanel1.add(jButton1, null);
jPanel1.add(jRadioButton1, null);
jPanel1.add(jToggleButton1, null);
jPanel1.add(jCheckBox1, null);
jPanel1.add(jTextField1, null);
jPanel1.add(jList1, null);
jPanel1.add(jProgressBar1, null);
jPanel1.add(jSlider1, null);
}
}
------------------------------------------------------
■ANTでthemepackをzip
拾って来たスキン集であるテーマパックをカスタマイズしたい!
ということで、以下のようなAntでIDEで逐一コンパイル前に
themepack.zipを作れば楽です。
<?xml version="1.0" encoding="utf-8"?>
<project name="zipThemepack" default="themepack.zipitup" basedir=".">
<property name="src" value="src/themepack/themepack/" />
<property name="dest" value="src/themepack/themepack.zip" />
<target name="themepack.zipitup">
<delete>
<fileset file="${dest}"/>
</delete>
<zip destfile="${dest}" basedir="${src}"/>
</target>
</project>
■JDialogのIconをかっこよく、というかダイアログのアイコン変更
LookAndFeelを使用しない場合に、JDialogの窓の左上には親JFrameの
アイコンと同じアイコンが表示される。しかしJDialogに対して
setDefaultLookAndFeelDecoratedをtrueにすると普通はアイコンが表示
されなくなる。しかしこのSkinを利用した場合はアイコンが表示される。
しかしアイコンがデフォルトのアイコンから変更できない!!
つまりこのSkinを使用した場合親JFrameのアイコンを子JDialogが
使ってくれない。根性で調べた限りではsetDefaultLookAndFeelDecorated
メソッドが関連している。たぶんsetDefaultLookAndFeelDecoratedを
trueにすると普通はiconが必要ないから親JFrameのicon情報を取得
できなくなるっぽいね。
解決方法は、このSKinの設定ファイルであるskinlf-themepack.xmlに
手を加えるという手があった。
<icon name="InternalFrame.icon" value="icons/Window.gif"/>
JDialogのアイコンはInternalFrameのアイコンとして認識するみたいだね〜
このスキンでは。pngもいけるのでしょうか?試してません。
----------- 全体 ------------------
<?xml version="1.0"?>
<skinlf-themepack require="1.2.4">
<property name="EnableBorders" value="true" />
<property name="JDesktopPane.backgroundEnabled" value="false" />
<property name="ScrollBar.alternateLayout" value="true" />
<property name="PopupMenu.animation" value="false"/>
<property name="JSplitPane.alternateUI" value="true" />
<icon name="InternalFrame.icon" value="icons/Window.gif"/>
<font name="Global" value="SansSerif,0,11"/>
<skin>
<skin url="gtk/gtkrc"></skin>
<skin url="kde/kde.themerc"></skin>
</skin>
</skinlf-themepack>
-----------------------------
JavaのGraphics日本語表示について
java jpg作成 jpeg作成 jpg jpeg 画像作成
ちょっとjava.awt.Graphicsを使ってグラフを表示するツールを作っていたんだけど、
Solarisでは日本語が出たのにLinuxに持ってきた途端、日本語が表示できなくなってしまった!!
経験みんなある気がする。てかGraphicsを使ってjpg画像の作り方知ってる?案外調べないと
分からなかったからきっと有益だね。正しいかは分からんけどね〜。
どういう風に日本語が化けてしまうかというと「□」に化けてしまう。
SolarisからLinuxにプラットフォームを変えたときに起きたもんだからShiftJisとEUC-JPの
関連の問題かとてっきり思って色々byte変換してみて試したけどさっぱりだめ!
そこでふと冷静に考えると「□」って化けてるけど、エンコーディングの
問題の場合は「?」になるよな?という、最初から気づくべき事に相当後で気づいた。
あぁ、Graphicsで用いているFontに日本語が入ってないんじゃないのか?という
ことに気づいたわけです。
そこで全てのFontを表示させてみたくなるわけで、調べた所、GraphicsEnvironment
クラスのgetAllFontsメソッドで使えるフォント全部取得できるみたい。
それと日本語を表示できるフォントかどうかという見極めにはきっとたぶん
FontクラスのcanDisplay('あ')という感じでやればOKみたいだ。
これさえ知ればそれなりのフォントでどのプラットフォームでも日本語を表示
できるんじゃないかな?
結局以下のようなコードで一覧を出させてみた。
ついでにJPEG出力の方法のサンプルにもなる。
package untitled4;
import java.io.*;
import java.awt.*;
import java.awt.image.*;
import com.sun.image.codec.jpeg.*;
public class Untitled1 {
public static void main(String[] args) throws Exception{
//get all fonts
Font [] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
//decide size
int width=640;
int unit=20;
int height = unit * (fonts.length+1);
//make image
BufferedImage bufImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
//get graphics
Graphics g = bufImage.getGraphics();
//draw string by default font
g.setColor(new Color(255, 255, 0));
String env = System.getProperty("os.name") + ":" + System.getProperty("java.version") + ":" + System.getProperty("file.encoding");
g.drawString(g.getFont().canDisplay('あ') + ":" + g.getFont().getName() + ":" + "日本語〜−島屋芸能人" + env, 0, unit);
//draw string by all fonts
g.setColor(new Color(255, 255, 255));
for(int i = 0; i < fonts.length; i++){
g.setColor(new Color((i*30) % 255, (i*10) % 150 + 100, (i*15) % 150 + 100));
g.setFont(new Font(fonts[i].getName(), Font.PLAIN, 20));
g.drawString(fonts[i].canDisplay('あ') + ":" + fonts[i].getName() + ":" + "日本語〜−島屋芸能人", 0, (i+2)*unit);
}
//to jpg byte array
ByteArrayOutputStream bout = new ByteArrayOutputStream();
JPEGImageEncoder jpegImageEncoder = JPEGCodec.createJPEGEncoder(bout);
jpegImageEncoder.encode(bufImage, JPEGCodec.getDefaultJPEGEncodeParam(bufImage));
//save to file
FileOutputStream fout =new FileOutputStream("test.jpg");
fout.write(bout.toByteArray());
fout.close();
}
}
なんか白だけじゃさびしかったので要らないコードがなんか混ざってますが。
LinuxとかSolarisでの実行時には注意!これをただ単に実行すると多分
Exception in thread "main" java.lang.InternalError: Can't connect to X11 window server using ':0.0' as the value
of the DISPLAY variable.
at sun.awt.X11GraphicsEnvironment.initDisplay(Native Method)
at sun.awt.X11GraphicsEnvironment.<clinit>(X11GraphicsEnvironment.java:134)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:141)
at java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:62)
at untitled4.Untitled1.main(Untitled1.java:12)
こんな事言われてしまいます。よく分からないけどAWTはXサーバ無いと基本は動かない、のかなぁ?
詳しい事はほっといて実行時に-Djava.awt.headless=trueを定義してやればOKです。ただしかし、これでごまかせるのは
1.4系のみっぽいけど、それもようわからんけど、まぁいまさら1.3使わなくてもね〜。
例)java -Djava.awt.headless=true -jar untitled4.jar
とりあえず以下の3環境でなんとなく表示さsてみた。
SunOS 5.8 Generic_108528-13 sun4u sparc SUNW,UltraSPARC-IIi-cEngine
Linux 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686 i386 GNU/Linux
Windows 2000
なるほど、デフォルトのフォントで何故かRedHatLinux9だけ日本語対応してないのね!
そりゃ日本語表示上手くいかないわ。フォントなんてどれでもいいからとにかく日本語が
表示できりゃいいんだからデフォルトは勝手に日本語OKなフォントにしてくれよな〜。
Linuxで日本語対応しているフォントですらタカシマヤの島屋の「」がかけてる。
外字的な文字には対応してないって事だねぇ。
ちょっと仕事用では辛いねぇ。
Java の 日本語 化け 化ける 対策 対策方法
■始めに
Javaをやっているとよう日本語が化ける。Windows上では問題なかったのに
LinuxとかSolarisに持っていくと化けが発生する事がようある。これは
本当にめんどくさい!日本語をJavaで扱う場合、UTF-8,UNICODE,MS932,
SJIS,EUC_JP,ISO2022JP辺りを気にしなきゃならない。めんどくさい。
基本的な説明は抜きにして、実践的にどうするをメモしとこうっと。
■前提調査
以下のコードで各コードが最終的にどんなバイト配列かチェックする。
ISO2022JPはトリッキーだしメール送信ぐらいでしか関係ないからシカト
それと最初しらなかったんだけど、SJISとMS932は違うエンコーディング。
SJISは元々のShift JISのエンコーディングでMS932がマイクロソフトが
Shift JISを拡張したエンコーディングかなんか。
package bake;
public class Bake1 {
public static void main(String [] args) throws Exception{
print("?");
}
public static void print(String str) throws Exception{
System.out.println("-- " + str + " --");
System.out.println("MS932:");
System.out.println(toHex(str.getBytes("MS932")));
System.out.println();
System.out.println("SJIS:");
System.out.println(toHex(str.getBytes("SJIS")));
System.out.println();
System.out.println("EUC_JP:");
System.out.println(toHex(str.getBytes("EUC_JP")));
System.out.println();
System.out.println("UTF8:");
System.out.println(toHex(str.getBytes("UTF8")));
System.out.println("----");
}
public static String toHex(byte [] b){
int intervalEnter = 16;
int intervalSpace = 4;
StringBuffer sb = new StringBuffer();
for(int i = 0; b != null && i < b.length; i++){
sb.append(Integer.toHexString(0xff & b[i]));
if(i % intervalEnter == intervalEnter - 1){
sb.append("\n");
}else if(i % intervalSpace == intervalSpace - 1){
sb.append(" ");
}else{
// sb.append(" ");
}
}
if(sb.length() > 0){
return sb.toString();
}else{
return null;
}
}
}
○結果
-- ? --
MS932:3f
SJIS:3f
EUC_JP:3f
UTF8:3f
----
-- 〜 --
MS932:8160
SJIS:3f
EUC_JP:8fa2b7
UTF8:efbd9e
----
-- --
MS932:fbfc
SJIS:3f
EUC_JP:3f
UTF8:e9ab99
----
-- − --
MS932:817c
SJIS:3f
EUC_JP:3f
UTF8:efbc8d
----
-- 芸能 --
MS932:8c7c945c
SJIS:8c7c945c
EUC_JP:b7ddc7bd
UTF8:e88ab8e8 83bd
----
「〜」と「」では化けパターンが違う。
「」はEUC_JPでもSJISでもまじで[?]になっててダメだけど、
「〜」はEUC_JPだとそれなりに変換されている。
詳しいことは分からないけど、「」などの難しい漢字は
エンコーディングによっては元々存在しないっぽい。
「〜」などの微妙な文字はエンコーディング間でのマッピング
が狂ってるっぽい。
■文字化けパターン
化けのパターンとしては2パターンある。エンコードを全く間違えて
メチャクチャな文字列になっちゃうのは作った奴のあからさまなミスなので
ここではシカト。
○全部[?]になる!
これはJ2EEサーバでまともに日本語の設定をしないと起きる。
POST/GETしてrequest.getParameterしてびっくりみたいな。
○「〜」とか「−」とか「」みたいな難しい漢字が[?]に化ける!
これはPOST/GETの時のほかに、ファイルに書き出した場合
によく遭遇する。ファイルに吐き出したもののファイル自体が
化けてたり、ファイルはOKだったのに読み込んだらおかしくなったり。
あと、何気にまじめにメール送信する場合も問題になる。
■原因
○全部[?]になる!原因
全部?になるようなパターンは、どこかで日本語を英語文字列として
認識しちゃった場合に大抵起きる。
String b = new String("はてな".getBytes("MS932"), "ISO-8859-1");
という状態だと多分思う。
しかしこの場合、表面上は[?]でもバイトコードは保持されているみたいだ。
○「〜」とか「−」とか「」みたいな難しい漢字が[?]に化ける!原因
これは日本語エンコーディングの変換がどこかで行われてしまうから
起きる場合が大抵な気がする。MS932でPOSTされた文字列を、ファイルに
SJISでしまいこんで、ファイルを読み込んで画面にMS932で表示とかね。
String b = new String("あいう〜−島屋".getBytes("MS932"), "SJIS");
ようは上記の状態みたいな事がおきるんかと。
■小手先解決方法
全部[?]になる!場合はバイトコードは3f3f3f..となるわけじゃなく
元のが残る、というか、ASCIIだから何にも変換を試みないだけだろうけど。
つまり、無理矢理復旧が結構可能みたいだ。
new String(iso88591.getBytes("ISO-8859-1"), "MS932");
多分誰もがこれでごまかした事があるんじゃないかね?
しかし完全に小手先技。他人が作ったもので根本的に直せない場合
以外は使いたくない。だってかっこわるいもん。コード的に。
■根本的解決方法
○全部[?]になる!解決方法
これは大抵J2EEサーバの設定が足りなくて起きるかなぁ。
Tomcatで言ったらどこかで書いたようにserver.xmlのなかの
connecterかなんかの要素にURIEncodingとかなんかの属性で
GETパラメータというか、URIのエンコーディングの指定と
request.setCharacterEncodingかなんかでPOSTパラメータの
エンコーディングの設定をする。
WebLogicだったらWebLogic.xmlになんか設定すればOKなきが。
この問題に関しては大抵これで直るきが。
J2EEではなく、単純なシェルキックなVMで???になっちゃう場合は
VMのデフォルトエンコーディングが英語状態になってる可能性が。
その場合はLANGだかなんかの環境変数を日本語にしちゃえばOK.
○「〜」とか「−」とか「」みたいな難しい漢字が[?]に化ける!解決方法
これはどこかで文字列をバイト配列に変換する、また逆にバイト配列
を文字列に変換するところで、デフォルトエンコーディングを使わない、
つまり、エンコーディングを必ず指定するようにすれば多分OK.
てか、俺の場合はMS932に画面表示でMS932でPOSTされてというのが
今のデファクトスタンダードだと思ってるので、全てMS932を使うように
心がけてる。しかし大抵どこか忘れる。忘れた時には大体以下のような
クラス/メソッド/コンストラクタが使われてる所を探せば大抵原因にぶち当たる。
java.net.URLEncoder
java.net.URLDecoder
java.io.Writer系全般
java.io.Reader系全般
String.getBytes()
new String()
java.io.InputStreamReader
java.io.OutputStreamWriter
大抵サラサラ〜とコードを追って、これらが使われている所が原因だねぇ。
これらを使う時に全部MS932にしちゃえば問題が起きなくなる。
しかし、Writer/Reader系とかで極悪な事にプラットフォームのエンコーディング
の呪縛から逃れられない場合があった気がする。1.3の時だけかな?
よく覚えてないけど、そういう時はInputStreamReader/OutputStreamWriter
辺りを使ってごまかせたきがする。
■まとめ
さっさと日本語エンコーディング一つに統一しろボケ!
■JSPのpageディレクティブ
JSPの最初の行にこういうのを書くと思う。
<%@ page contentType="text/html; charset=Shift_JIS" %>
一体これは何の役目だ??と言う事をまず知らなければならぬ。
というわけで、調べました。
結果として、これには二つの役割がありました。
・response.setContentTypeの設定
・JSP->JAVA変換時のJSPのコード設定
○response.setContentTypeとしての役割
contentType属性値をそのままsetContentTypeメソッドに
渡すみたい。例えば
<%@ page contentType="text/htmls; charset=MS932" %>
と適当なことを書くと、JAVAソースでは以下の様になりました。
response.setContentType("text/htmls; charset=MS932");
○JSP->JAVA変換時の役割
ポイントとしては、JSPから生成されたJAVAファイルはUTF8でした。
つまり、JSPファイルをUTF8のJAVAファイルに変換する為のエンコーディング
指定。
○実例:
JSP(MS932):
<%@ page contentType="text/html; charset=MS932" %>
〜−
...
JAVA(UTF8):
response.setContentType("text/html; charset=MS932");
...
out.write("〜−\r\n");
...
----------------------------------------------
JSP(MS932):
<%@ page contentType="text/html; charset=Shift_JIS" %>
〜−
...
JAVA(UTF8):
response.setContentType("text/html; charset=Shift_JIS");
out.write("????\r\n");
----------------------------------------------
JSP(MS932):
<%@ page contentType="text/html; charset=EUC_JP" %>
〜−
...
JAVA(UTF8):
response.setContentType("text/html; charset=EUC_JP");
out.write("???\r\n");
----------------------------------------------
JSP(EUC_JP):
<%@ page contentType="text/html; charset=EUC_JP" %>
〜−
...
JAVA(UTF8):
response.setContentType("text/html; charset=EUC_JP");
out.write("???\r\n");
-----------------------------------------------------
■各ブラウザのエンコーディング変更時の動作
以上のことから、コードレベルで正しくUTF8に変換してもらうには
pageディレクティブにShift_JISではなく、MS932を指定しなきゃならない?
しかし、試した所、レスポンスヘッダのcharsetとしてMS932と入力しても
ブラウザは認識してくれないようだ。よくありがちな下のメタタグを
追加すればOKみたい。
レスポンスヘッダのcharsetを理解できない場合はメタタグのcharsetを使ってくれるようだ。
○実験
前画面がEUC_JPの時に、head(MS932),meta(Shift_JIS)を
送りつけた時にShift_JISに変わるか?
OPERA 7.23 OK
IE 6.0 OK
NC 4.78 OK
Netscape 7.1 OK
■結果
<%@ page contentType="text/html; charset=MS932" %>
としてやれば上手くいく。
■Tomcat 5.0.19でのPOST/GETパラメータのエンコーディング設定
以前のバージョンで散々悩んだ個所がadminコンソールで設定できるように!
てか、機能が増えた!
http://jakarta.apache.org/tomcat/tomcat-5.0-doc/changelog.html
Add support for URIEncoding, useBodyEncodingForURI, and allowTrace properties on the connector
(larryi)
確かに増えてる。日本語だと
・「URIエンコーディング」
・「URIクエリパラメータにボディのエンコーディングを使用」
つうのだね。
URIエンコーディングは前に調べた通り、GETパラメータのエンコーディング指定である。
useBodyEncodingForURIはなんだ?と言う事で調べた。
結果、useBodyEncodingForURIをtrueにする事というのはつまり、
「request.getCharacterEncodingの値をURIEncodingの値として使うよ」
という事みたいだ。つまり、request.setCharacterEncodingをしておけば
POST/GETともにその値を使ってくれるようになるみたいだ。
便利は便利なんだけど、URIEncodingの値をrequest.setCharacter..してくれた方が
楽なんだけどなぁ。
ちなみにこれはコネクタレベルで設定する。つまり、AJP,HTTP,HTTPSなどで個別に
設定となる。結構落とし穴かも。てか思いっきり見落としてた。
--
|