2014年5月13日 星期二

如何更改 JFrame 的整體字型大小

昨天遇到一個 Java Swing 的問題, 我在家裡的 17 吋螢幕 (1024x768) 顯示 JFrame 時, 視窗中的字型大小適中, 但在公司執行時卻變得很小, 原因就是公司電腦解析度較高 (1920x1080), 字反而變小. 即使將顯示設定改為 150% 大字也是一樣.

我試過呼叫 JFrame 源自 Container 的 setFont() 方法, 無效 :

f.setFont(new Font("Tahoma",Font.PLAIN,20));

例如 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class mytest {
  JFrame f;
  Container cp;
  public static void main(String argv[]) {
    new mytest();
    }
  public mytest() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JFrame Test");
    f.setSize(400,300);
    f.setFont(new Font("Tahoma",Font.PLAIN,20));  //無效
    f.setLocationRelativeTo(null);
    cp=f.getContentPane();
    cp.setLayout(null);

    //Build Elements
    JLabel label=new JLabel("Hello World");
    label.setBounds(50,50,100,40);
    cp.add(label);
    f.setVisible(true);

    //Close JFrame      
    f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        int result=JOptionPane.showConfirmDialog(f,
                   "確定要結束程式嗎?",
                   "確認訊息",
                   JOptionPane.YES_NO_OPTION,
                   JOptionPane.WARNING_MESSAGE);
        if (result==JOptionPane.YES_OPTION) {System.exit(0);}
        }  
      });
    }
  }



看起來似乎字型不會太小, 但這是抓圖會放大的效果, 實際上在解析度高的螢幕上看起來較小. 要如何整體改變 JFrame 的字型大小呢? 我找到下列文章, 測試結果 OK :

Setting the Default Font of Swing Program in Java
Change Font type and size for the whole JFrame?

範例如下 :

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import javax.swing.plaf.FontUIResource;

public class mytest {
  JFrame f;
  Container cp;
  public static void main(String argv[]) {
    new mytest();
    }
  public mytest() {
    //Setup JFrame
    JFrame.setDefaultLookAndFeelDecorated(true);
    JDialog.setDefaultLookAndFeelDecorated(true);
    f=new JFrame("JFrame Test");
    f.setSize(400,300);
    setUIFont(new FontUIResource("新細明體",Font.ITALIC,20));
    f.setLocationRelativeTo(null);
    cp=f.getContentPane();
    cp.setLayout(null);

    //Build Elements
    JLabel label=new JLabel("Hello World");
    label.setBounds(50,50,100,40);
    cp.add(label);
    f.setVisible(true);

    //Close JFrame      
    f.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        int result=JOptionPane.showConfirmDialog(f,
                   "確定要結束程式嗎?",
                   "確認訊息",
                   JOptionPane.YES_NO_OPTION,
                   JOptionPane.WARNING_MESSAGE);
        if (result==JOptionPane.YES_OPTION) {System.exit(0);}
        }  
      });
    }
  public void setUIFont (FontUIResource fui){
    Enumeration keys=UIManager.getDefaults().keys();
    while (keys.hasMoreElements()) {
      Object key=keys.nextElement();
      Object value=UIManager.get(key);
      if (value != null && value instanceof FontUIResource) {
        UIManager.put(key, fui);
        }
      } 
    }
  }


這裡要用到 java.util.Enumeration 與 javax.swing.plaf.FontUIResource 類別, 因此要特別匯入 java.util 套件與 FontUIResource 類別. 這個自訂的 setUIFont() 方法會使 JFrame 內所有 GUI 元件裡的文字都套用 FontUIResource 物件之字型設定 (但 JFrame 的標題除外).

但是要注意, 若程式中有用到中文, 則必須設定中文字型, 否則會出現亂碼, 例如若將上例的字型改為 Tahoma :

setUIFont(new FontUIResource("Tahoma",Font.ITALIC,20));

則關閉視窗時, 確認視窗中的中文都變成亂碼了 :




沒有留言 :