Java Swing 寫的字型選擇器,仿記事本中的字型控件,使用操作方法與檔案選擇器JFileChooser基本相同。
package net.miqiang.gui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
/**
* 字型選擇器,仿記事本中的字型控件,使用操作方法與檔案選擇器JFileChooser基本相同。
* @author 米強<轉載請注明作者與來源>
* @blog http://blog.csdn.net/mq612
* @blog http://hi.baidu.com/mq612/blog
*
*/
@SuppressWarnings("serial")
public class MQFontChooser extends JDialog {
/**
* 選擇取消按鈕的傳回值
*/
public static final int CANCEL_OPTION = 0;
/**
* 選擇确定按鈕的傳回值
*/
public static final int APPROVE_OPTION = 1;
/**
* 中文預覽的字元串
*/
private static final String CHINA_STRING = "神馬都是浮雲!";
/**
* 英文預覽的字元串
*/
private static final String ENGLISH_STRING = "Hello Kitty!";
/**
* 數字預覽的字元串
*/
private static final String NUMBER_STRING = "0123456789";
// 預設字型,也是将來要傳回的字型
private Font font = null;
// 字型選擇器元件容器
private Box box = null;
// 字型文本框
private JTextField fontText = null;
// 樣式文本框
private JTextField styleText = null;
// 文字大小文本框
private JTextField sizeText = null;
// 預覽文本框
private JTextField previewText = null;
// 中文預覽
private JRadioButton chinaButton = null;
// 英文預覽
private JRadioButton englishButton = null;
// 數字預覽
private JRadioButton numberButton = null;
// 字型選擇框
private JList fontList = null;
// 樣式選擇器
private JList styleList = null;
// 文字大小選擇器
private JList sizeList = null;
// 确定按鈕
private JButton approveButton = null;
// 取消按鈕
private JButton cancelButton = null;
// 所有字型
private String [] fontArray = null;
// 所有樣式
private String [] styleArray = {"正常", "粗體", "斜體", "粗斜體"};
// 所有預設字型大小
private String [] sizeArray = {"8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24", "26", "28", "36", "48", "初号", "小初", "一号", "小一", "二号", "小二", "三号", "小三", "四号", "小四", "五号", "小五", "六号", "小六", "七号", "八号"};
// 上面數組中對應的字型大小
private int [] sizeIntArray = {8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 42, 36, 26, 24, 22, 18, 16, 15, 14, 12, 10, 9, 8, 7, 6, 5};
// 傳回的數值,預設取消
private int returnValue = CANCEL_OPTION;
/**
* 體構造一個字型選擇器
*/
public MQFontChooser() {
this(new Font("宋體", Font.PLAIN, 12));
}
/**
* 使用給定的預設字型構造一個字型選擇器
* @param font 字型
*/
public MQFontChooser(Font font) {
setTitle("字型選擇器");
this.font = font;
// 初始化UI元件
init();
// 添加監聽器
addListener();
// 按照預設字型顯示
setup();
// 基本設定
setModal(true);
setResizable(false);
// 自适應大小
pack();
}
/**
* 初始化元件
*/
private void init(){
// 獲得系統字型
GraphicsEnvironment eq = GraphicsEnvironment.getLocalGraphicsEnvironment();
fontArray = eq.getAvailableFontFamilyNames();
// 主容器
box = Box.createVerticalBox();
box.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
fontText = new JTextField();
fontText.setEditable(false);
fontText.setBackground(Color.WHITE);
styleText = new JTextField();
styleText.setEditable(false);
styleText.setBackground(Color.WHITE);
sizeText = new JTextField("12");
// 給文字大小文本框使用的Document文檔,制定了一些輸入字元的規則
Document doc = new PlainDocument(){
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException {
if (str == null) {
return;
}
if (getLength() >= 3) {
return;
}
if (!str.matches("[0-9]+") && !str.equals("初号") && !str.equals("小初") && !str.equals("一号") && !str.equals("小一") && !str.equals("二号") && !str.equals("小二") && !str.equals("三号") && !str.equals("小三") && !str.equals("四号") && !str.equals("小四") && !str.equals("五号") && !str.equals("小五") && !str.equals("六号") && !str.equals("小六") && !str.equals("七号") && !str.equals("八号")) {
return;
}
super.insertString(offs, str, a);
sizeList.setSelectedValue(sizeText.getText(), true);
}
};
sizeText.setDocument(doc);
previewText = new JTextField(20);
previewText.setHorizontalAlignment(JTextField.CENTER);
previewText.setEditable(false);
previewText.setBackground(Color.WHITE);
chinaButton = new JRadioButton("中文預覽", true);
englishButton = new JRadioButton("英文預覽");
numberButton = new JRadioButton("數字預覽");
ButtonGroup bg = new ButtonGroup();
bg.add(chinaButton);
bg.add(englishButton);
bg.add(numberButton);
fontList = new JList(fontArray);
styleList = new JList(styleArray);
sizeList = new JList(sizeArray);
approveButton = new JButton("确定");
cancelButton = new JButton("取消");
Box box1 = Box.createHorizontalBox();
JLabel l1 = new JLabel("字型:");
JLabel l2 = new JLabel("字形:");
JLabel l3 = new JLabel("大小:");
l1.setPreferredSize(new Dimension(165, 14));
l1.setMaximumSize(new Dimension(165, 14));
l1.setMinimumSize(new Dimension(165, 14));
l2.setPreferredSize(new Dimension(95, 14));
l2.setMaximumSize(new Dimension(95, 14));
l2.setMinimumSize(new Dimension(95, 14));
l3.setPreferredSize(new Dimension(80, 14));
l3.setMaximumSize(new Dimension(80, 14));
l3.setMinimumSize(new Dimension(80, 14));
box1.add(l1);
box1.add(l2);
box1.add(l3);
Box box2 = Box.createHorizontalBox();
fontText.setPreferredSize(new Dimension(160, 20));
fontText.setMaximumSize(new Dimension(160, 20));
fontText.setMinimumSize(new Dimension(160, 20));
box2.add(fontText);
box2.add(Box.createHorizontalStrut(5));
styleText.setPreferredSize(new Dimension(90, 20));
styleText.setMaximumSize(new Dimension(90, 20));
styleText.setMinimumSize(new Dimension(90, 20));
box2.add(styleText);
box2.add(Box.createHorizontalStrut(5));
sizeText.setPreferredSize(new Dimension(80, 20));
sizeText.setMaximumSize(new Dimension(80, 20));
sizeText.setMinimumSize(new Dimension(80, 20));
box2.add(sizeText);
Box box3 = Box.createHorizontalBox();
JScrollPane sp1 = new JScrollPane(fontList);
sp1.setPreferredSize(new Dimension(160, 100));
sp1.setMaximumSize(new Dimension(160, 100));
sp1.setMaximumSize(new Dimension(160, 100));
box3.add(sp1);
box3.add(Box.createHorizontalStrut(5));
JScrollPane sp2 = new JScrollPane(styleList);
sp2.setPreferredSize(new Dimension(90, 100));
sp2.setMaximumSize(new Dimension(90, 100));
sp2.setMinimumSize(new Dimension(90, 100));
box3.add(sp2);
box3.add(Box.createHorizontalStrut(5));
JScrollPane sp3 = new JScrollPane(sizeList);
sp3.setPreferredSize(new Dimension(80, 100));
sp3.setMaximumSize(new Dimension(80, 100));
sp3.setMinimumSize(new Dimension(80, 100));
box3.add(sp3);
Box box4 = Box.createHorizontalBox();
Box box5 = Box.createVerticalBox();
JPanel box6 = new JPanel(new BorderLayout());
box5.setBorder(BorderFactory.createTitledBorder("字元集"));
box6.setBorder(BorderFactory.createTitledBorder("示例"));
box5.add(chinaButton);
box5.add(englishButton);
box5.add(numberButton);
box5.setPreferredSize(new Dimension(90, 95));
box5.setMaximumSize(new Dimension(90, 95));
box5.setMinimumSize(new Dimension(90, 95));
box6.add(previewText);
box6.setPreferredSize(new Dimension(250, 95));
box6.setMaximumSize(new Dimension(250, 95));
box6.setMinimumSize(new Dimension(250, 95));
box4.add(box5);
box4.add(Box.createHorizontalStrut(4));
box4.add(box6);
Box box7 = Box.createHorizontalBox();
box7.add(Box.createHorizontalGlue());
box7.add(approveButton);
box7.add(Box.createHorizontalStrut(5));
box7.add(cancelButton);
box.add(box1);
box.add(box2);
box.add(box3);
box.add(Box.createVerticalStrut(5));
box.add(box4);
box.add(Box.createVerticalStrut(5));
box.add(box7);
getContentPane().add(box);
}
/**
* 按照預設字型顯示
*/
private void setup() {
String fontName = font.getFamily();
int fontStyle = font.getStyle();
int fontSize = font.getSize();
/*
* 如果預設的文字大小在選擇清單中,則通過選擇該清單中的某項進行設值,否則直接将預設文字大小寫入文本框
*/
boolean b = false;
for (int i = 0; i < sizeArray.length; i++) {
if (sizeArray[i].equals(String.valueOf(fontSize))) {
b = true;
break;
}
}
if(b){
// 選擇文字大小清單中的某項
sizeList.setSelectedValue(String.valueOf(fontSize), true);
}else{
sizeText.setText(String.valueOf(fontSize));
}
// 選擇字型清單中的某項
fontList.setSelectedValue(fontName, true);
// 選擇樣式清單中的某項
styleList.setSelectedIndex(fontStyle);
// 預覽預設顯示中文字元
chinaButton.doClick();
// 顯示預覽
setPreview();
}
/**
* 添加所需的事件監聽器
*/
private void addListener() {
sizeText.addFocusListener(new FocusListener() {
public void focusLost(FocusEvent e) {
setPreview();
}
public void focusGained(FocusEvent e) {
sizeText.selectAll();
}
});
// 字型清單發生選擇事件的監聽器
fontList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
fontText.setText(String.valueOf(fontList.getSelectedValue()));
// 設定預覽
setPreview();
}
}
});
styleList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
styleText.setText(String.valueOf(styleList.getSelectedValue()));
// 設定預覽
setPreview();
}
}
});
sizeList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
if(!sizeText.isFocusOwner()){
sizeText.setText(String.valueOf(sizeList.getSelectedValue()));
}
// 設定預覽
setPreview();
}
}
});
// 編碼監聽器
EncodeAction ea = new EncodeAction();
chinaButton.addActionListener(ea);
englishButton.addActionListener(ea);
numberButton.addActionListener(ea);
// 确定按鈕的事件監聽
approveButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 組合字型
font = groupFont();
// 設定傳回值
returnValue = APPROVE_OPTION;
// 關閉視窗
disposeDialog();
}
});
// 取消按鈕事件監聽
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
disposeDialog();
}
});
}
/**
* 顯示字型選擇器
* @param owner 上層所有者
* @return 該整形傳回值表示使用者點選了字型選擇器的确定按鈕或取消按鈕,參考本類常量字段APPROVE_OPTION和CANCEL_OPTION
*/
public final int showFontDialog(JFrame owner) {
setLocationRelativeTo(owner);
setVisible(true);
return returnValue;
}
/**
* 傳回選擇的字型對象
* @return 字型對象
*/
public final Font getSelectFont() {
return font;
}
/**
* 關閉視窗
*/
private void disposeDialog() {
MQFontChooser.this.removeAll();
MQFontChooser.this.dispose();
}
/**
* 顯示錯誤消息
* @param errorMessage 錯誤消息
*/
private void showErrorDialog(String errorMessage) {
JOptionPane.showMessageDialog(this, errorMessage, "錯誤", JOptionPane.ERROR_MESSAGE);
}
/**
* 設定預覽
*/
private void setPreview() {
Font f = groupFont();
previewText.setFont(f);
}
/**
* 按照選擇組合字型
* @return 字型
*/
private Font groupFont() {
String fontName = fontText.getText();
int fontStyle = styleList.getSelectedIndex();
String sizeStr = sizeText.getText().trim();
// 如果沒有輸入
if(sizeStr.length() == 0) {
showErrorDialog("字型(大小)必須是有效“數值!");
return null;
}
int fontSize = 0;
// 通過循環對比文字大小輸入是否在現有清單内
for (int i = 0; i < sizeArray.length; i++) {
if(sizeStr.equals(sizeArray[i])){
fontSize = sizeIntArray[i];
break;
}
}
// 沒有在清單内
if (fontSize == 0) {
try{
fontSize = Integer.parseInt(sizeStr);
if(fontSize < 1){
showErrorDialog("字型(大小)必須是有效“數值”!");
return null;
}
}catch (NumberFormatException nfe) {
showErrorDialog("字型(大小)必須是有效“數值”!");
return null;
}
}
return new Font(fontName, fontStyle, fontSize);
}
/**
* 編碼選擇事件的監聽動作
* @author 米強
*
*/
class EncodeAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(chinaButton)) {
previewText.setText(CHINA_STRING);
} else if (e.getSource().equals(englishButton)) {
previewText.setText(ENGLISH_STRING);
} else {
previewText.setText(NUMBER_STRING);
}
}
}
}
下面是一個測試類,需要單獨建一個TestMain.java檔案
package net.miqiang.gui;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
/**
* 字型選擇器測試類
* @author 米強
*
*/
public class TestMain extends JFrame {
private JTextArea text = null;
private JButton button = null;
static {
try {
// 請配合Look And Feel使用本元件,可得到更好的效果
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
public TestMain() {
text = new JTextArea("五星紅旗迎風飄揚,/n勝利歌聲多麼響亮;/n歌唱我們親愛的祖國,/n從今走向繁榮富強。/n歌唱我們親愛的祖國,/n從今走向繁榮富強。/n/n越過高山,/n越過平原,/n跨過奔騰的黃河長江;/n寬廣美麗的土地,/n是我們親愛的家鄉,/n英雄的人民站起來了!/n我們團結友愛堅強如鋼。");
System.out.println(text.getFont());
button = new JButton("設定字型");
// 給按鈕添加動作事件監聽
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// 構造字型選擇器,參數字型為預設值
MQFontChooser fontChooser = new MQFontChooser(text.getFont());
// 打開一個字型選擇器視窗,參數為父級所有者窗體。傳回一個整型,代表設定字型時按下了确定或是取消,可參考MQFontChooser.APPROVE_OPTION和MQFontChooser.CANCEL_OPTION
int returnValue = fontChooser.showFontDialog(TestMain.this);
// 如果按下的是确定按鈕
if (returnValue == MQFontChooser.APPROVE_OPTION) {
// 擷取選擇的字型
Font font = fontChooser.getSelectFont();
// 将字型設定到JTextArea中
text.setFont(font);
}
}
});
getContentPane().add(new JScrollPane(text));
getContentPane().add(button, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new TestMain();
}
}