• 追加された行はこの色です。
  • 削除された行はこの色です。
TITLE:UIManagerで使用するFontを統一
#navi(../)
RIGHT:Posted by [[terai]] at 2003-10-01
#tags()
RIGHT:Posted by &author(aterai); at 2003-10-01
*UIManagerで使用するFontを統一 [#u24f3fb9]
Swingの各種コンポーネントで使用する全てのフォントを一気に変更します。[[JavaHouse-Brewers:49474 Re: setFont に関して>http://java-house.jp/ml/archive/j-h-b/049474.html]]から引用しています。
Swingの各種コンポーネントで使用する全てのフォントを一気に変更します。

-&jnlp;
-&jar;
-&zip;

#screenshot
//#screenshot
#ref(http://lh4.ggpht.com/_9Z4BYR88imo/TQTNJ5XQrjI/AAAAAAAAAaU/lvxCohYLmBI/s800/FontChange.png)

**サンプルコード [#o65c96e5]
#code{{
#code(link){{
private void updateFont(final Font font) {
  FontUIResource fontUIResource = new FontUIResource(font);
  UIDefaults defaultTable = UIManager.getLookAndFeelDefaults();
  for(Object o: defaultTable.keySet()) {
    if(o.toString().toLowerCase().endsWith("font")) {
      UIManager.put(o, fontUIResource);
  for(java.util.Map.Entry<?,?> entry: UIManager.getDefaults().entrySet()) {
    if(entry.getKey().toString().toLowerCase().endsWith("font")) {
      UIManager.put(entry.getKey(), fontUIResource);
    }
  }
  //SwingUtilities.updateComponentTreeUI(this);
  recursiveUpdateUI(this);
  frame.pack();
}
private void recursiveUpdateUI(JComponent p) {
  for(Component c: p.getComponents()) {
    if(c instanceof JToolBar) {
      continue;
    }else if(c instanceof JComponent) {
      JComponent jc = (JComponent)c;
      jc.updateUI();
      if(jc.getComponentCount()>0) recursiveUpdateUI(jc);
    }
  }
}
}}

**解説 [#laf90233]
上記のサンプルでは、ツールバーのボタンでコンポーネントが使用するフォントを切り替えています。ただしツールバーだけは、UIのupdate(フォントの変更)を除外しています。

全部のコンポーネントではなく、例えばテーブルのフォントだけ変更したい場合は以下のように設定します。
#code{{
UIManager.put("Table.font", new FontUIResource(font));
}}

UIManagerのキー一覧を作るなどして、いろいろ検索してみてください。
UIManager から、UIDefaults のキー一覧を作るなどして、いろいろ検索してみてください。
#code{{
//キー一覧の作成例
import java.util.Map;
import javax.swing.UIManager;
class Test {
  public static void main(String[] args) {
    for(Object o:javax.swing.UIManager.getLookAndFeelDefaults().keySet())
      System.out.println(o);
    //for(Object o:UIManager.getDefaults().keySet()) //は、うまくいかない?
    //for(Object o:UIManager.getLookAndFeelDefaults().keySet())
    for(Map.Entry<?,?> entry: UIManager.getDefaults().entrySet())
      System.out.println(entry.getKey());
  }
}
}}

この方法は、一々[[LookAndFeel>http://java.sun.com/products/jlf/ed2/book/HIG.Glossary.html#51529]]を作成してフォントを変更するのが面倒なときには便利です。[[LookAndFeel>http://java.sun.com/products/jlf/ed2/book/HIG.Glossary.html#51529]]を自作する場合は、以下などを参考にしてみてください。
-[[Developing Accessible JFC Applications>http://www.sun.com/access/developers/developing-accessible-apps/]]
--[[Appendix A - LowVisionMetalLookAndFeel>http://www.sun.com/access/developers/developing-accessible-apps/appendix.html]]
-[[自分だけのカッコ良いアプリを作りたい,の巻>http://www2u.biglobe.ne.jp/~kaduhiko/java_09.html]]
この方法は、一々[http://java.sun.com/products/jlf/ed2/book/HIG.Glossary.html#51529 LookAndFeel]を作成してフォントを変更するのが面倒なときには便利です。[http://java.sun.com/products/jlf/ed2/book/HIG.Glossary.html#51529 LookAndFeel]を自作する場合は、以下などを参考にしてみてください。
-[http://www.sun.com/access/developers/developing-accessible-apps/ Developing Accessible JFC Applications]
--[http://www.sun.com/access/developers/developing-accessible-apps/appendix.html Appendix A - LowVisionMetalLookAndFeel]
-[http://www2u.biglobe.ne.jp/~kaduhiko/java_09.html 自分だけのカッコ良いアプリを作りたい,の巻]

また、フォントが気に入らないだけなら、Metalで使ってるフォントが格好悪いので、それを変更してやるだけでいいかもしれません((1.5以上ではかなり改良されている))。
----
Metalで使用されているフォントが気に入らないといった場合は、システムLook&Feelを使用するか、Metalでボールドフォントを無効にするなどの方法があります。
#code{{
//MetalLnFではなく、システムLook&Feelを使用する場合
try{
  UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(Exception e) {
  e.printStackTrace();
}
}}
#code{{
//MetalLnfで、bold fonts を無効にする場合
UIManager.put("swing.boldMetal", Boolean.FALSE);
}}
- http://docs.oracle.com/javase/jp/6/api/javax/swing/plaf/metal/DefaultMetalTheme.html

----
-JComboBox#setFontをしても、JComboBox自体のサイズが更新されない
--[[JCombobox doesn't get resized according to font size change>http://bugs.sun.com/view_bug.do?bug_id=5006246]]
--[http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5006246 JCombobox doesn't get resized according to font size change]
#code{{
combo.setFont(font);
//以下回避方法
combo.setPrototypeDisplayValue(null); //null:default?
//or combo.firePropertyChange("prototypeDisplayValue",0,1); //0,1:dummy
}}


**参考リンク [#sd5f9cb6]
-[[Re: setFont に関して>http://java-house.jp/ml/archive/j-h-b/049474.html]]
-[http://java-house.jp/ml/archive/j-h-b/049474.html Re: setFont に関して]

**コメント [#g0e08b07]
-JFileChooser インスタンス化前に上記ソースを実行すると ConcurrentModificationException がスローされるのですが... 「JDK1.4.2_02」プロパティーが動的に変化するとしたらあまり有効な方法でないのでは? -- [[MT]] SIZE(10){&new{2003-12-24 (水) 14:22:15};}
-割と手軽なので重宝するのですが、ちゃんとスレッド処理考えたほうがいいのかもしれませんね。 -- [[terai]] SIZE(10){&new{2003-12-25 (木) 20:06:15};}
-割と手軽なので重宝するのですが、ちゃんとスレッド処理考えたほうがいいのかもしれませんね。 -- [[aterai]] SIZE(10){&new{2003-12-25 (木) 20:06:15};}
-レスありがとうございます _ _)m とりあえず Container を辿りながら含まれている Component 毎に setFont 呼ぶようなユーティリティ用意してしのいでいます^^; -- [[MT]] SIZE(10){&new{2003-12-26 (金) 16:20:14};}
-UIManagerのリストにないコンポーネント(独自で作成したボタンなどのコンポーネント)なども追加すると変更が適用されるのでしょうか? -- [[mari]] SIZE(10){&new{2004-01-22 (木) 10:53:29};}
-JBottunなどのSwingコンポーネントを継承していれば変更されるはずです。 -- [[terai]] SIZE(10){&new{2004-01-22 (木) 11:46:40};}
-JBottunなどのSwingコンポーネントを継承していれば変更されるはずです。 -- [[aterai]] SIZE(10){&new{2004-01-22 (木) 11:46:40};}
-レスありがとうございます。その場合、独自のコンポーネントを追加すると、そのコンポーネントのみ変更が適用されますか?Panelを追加したら全てのpanelに適用されてしまってうまくいきませんでした。良い方法があったら教えてください。 -- [[mari]] SIZE(10){&new{2004-01-23 (金) 10:24:45};}
-すべてのコンポーネントに一々設定するのが面倒な場合のための方法なので、上記の場合は使用する意味が無いですね(^^;。ある独自コンポーネントのみフォントを変えたいのなら、コンストラクタなどで普通にsetFontすればいいのでないかと思うのですが、どうなんでしょう?そうじゃなくて、あるパネル以下のコンポーネントのフォントを一気に変えたいということなんでしょうか? -- [[terai]] SIZE(10){&new{2004-01-23 (金) 12:13:27};}
-すべてのコンポーネントに一々設定するのが面倒な場合のための方法なので、上記の場合は使用する意味が無いですね(^^;。ある独自コンポーネントのみフォントを変えたいのなら、コンストラクタなどで普通にsetFontすればいいのでないかと思うのですが、どうなんでしょう?そうじゃなくて、あるパネル以下のコンポーネントのフォントを一気に変えたいということなんでしょうか? -- [[aterai]] SIZE(10){&new{2004-01-23 (金) 12:13:27};}
-たびたびすみません。全体のフォントの大きさをツールバーの選択によって変化させるようにしたいです。フォントだけ変化させたいのですが、コンストラクタなどで勝手にsetBackgroundしているコンポーネントはLook and Feelで設定しているデフォルトのbackgroundに変わってしまいました。またnewするわけではないので、そのコンポーネントのみののデフォルトをどこかで設定できたらいいなー、と思いました。Look and Feelでもpanelだったらpanel全ての設定しかできないのでしょうか?有効な方法があったら教えてください。よろしくお願いいたします。 -- [[mari]] SIZE(10){&new{2004-01-23 (金) 14:05:47};}
-Look and Feelで変更するのではなく、イベントリスナーを作って実装するのはどうでしょう?はずしてるかもしれませんが、とりあえずサンプル置いておきます。初期値はコンストラクタで指定してます。ツールバーじゃなくてメニューで、フォントを切り替えてます。コンボボックスを切り替えたときにサイズがおかしいのは愛嬌ということで…。 -- [[terai]] SIZE(10){&new{2004-01-23 (金) 15:39:27};}
-Look and Feelで変更するのではなく、イベントリスナーを作って実装するのはどうでしょう?はずしてるかもしれませんが、とりあえずサンプル置いておきます。初期値はコンストラクタで指定してます。ツールバーじゃなくてメニューで、フォントを切り替えてます。コンボボックスを切り替えたときにサイズがおかしいのは愛嬌ということで…。 -- [[aterai]] SIZE(10){&new{2004-01-23 (金) 15:39:27};}
--[[EventListenerを実装して独自イベント作成>Swing/EventListener]]
-すばらしいサンプルありがとうございます!参考にさせていただきました☆フォントの変更をLook and Feelで行って、残りの描画できなかった背景色などをPropertyChangeListenerを実装して描画しなおす、という方法も考えたのですが、こちらでも問題ないでしょうか?主題から外れてしまって申し訳ありません・・・。 -- [[mari]] SIZE(10){&new{2004-01-26 (月) 09:56:38};}
-次のネタ用にイベント作っただけなので、PropertyChangeListener使うのはまったく問題ないと思います。むしろちゃんとJavaBeansにしてPropertyChangeListener使うほうがいいかもしれません(^^;。 -- [[terai]] SIZE(10){&new{2004-01-26 (月) 12:54:00};}
-次のネタ用にイベント作っただけなので、PropertyChangeListener使うのはまったく問題ないと思います。むしろちゃんとJavaBeansにしてPropertyChangeListener使うほうがいいかもしれません(^^;。 -- [[aterai]] SIZE(10){&new{2004-01-26 (月) 12:54:00};}

#comment