swing元件介紹(1)

dzgwt2006發表於2007-08-20
學習swing元件,主要有三個內容
一是元件的顯示,二是對元件支援的事件進行偵聽,三是是自定義元件
1.JFrame
JFrame是主視窗,它和JDialog,JApplet的地位並列.但是,一個JFrame可以新增JDialog和JApplet進去它的內容皮膚,而反過來就不行
下面來看JFrame的例子
=================================================

[code]
package blog.swing;
import javax.swing.*;
import java.awt.event.*;

class JFrameDemo
{
JFrame mainFrame;
public JFrameDemo() {
mainFrame = new JFrame ( "JFrameDemo Title" ); //建立一個JFrame
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );//設定關閉動作
mainFrame.setSize( 300,300 );//設定視窗大小
mainFrame.setLocationRelativeTo(null);//使視窗顯示在螢幕中央

mainFrame.addWindowListener( new WindowListener(){
public void windowOpened( WindowEvent e ){ System.out.println( "window opened" ); }
public void windowClosing( WindowEvent e ){ System.out.println( "window closing" ); }
public void windowClosed( WindowEvent e ){ System.out.println( "window closed" ); }
public void windowIconified( WindowEvent e ){ System.out.println( "window iconified" ); }
public void windowDeiconified( WindowEvent e ){ System.out.println( "window deiconified" ); }
public void windowActivated( WindowEvent e ){ System.out.println( "window activated" ); }
public void windowDeactivated( WindowEvent e ){ System.out.println( "window deactivated" ); }
});
mainFrame.addWindowFocusListener( new WindowFocusListener(){
public void windowGainedFocus( WindowEvent e ){ System.out.println( "gained focus" ); }
public void windowLostFocus( WindowEvent e ){ System.out.println( "lost focus" ); }
});
mainFrame.addWindowStateListener( new WindowStateListener(){
public void windowStateChanged( WindowEvent e ){ System.out.println( "state changed" ); }
});

mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JFrameDemo();
}
}

[/code]
==========================================================
這裡出現了三個不同的視窗事件偵聽器,並實現了它們所有的方法
WindowListener和WindowFocusListener都可以對視窗失去,獲得焦點進行偵聽,不同的是,非幀視窗和對話方塊視窗不能接收WindowListener的windowActivated和windodwDeactivated事件
雖然可以用WindowListener對視窗的一些狀態進行偵聽,但是WindowStateListener提供了更多的支援.例如,WindowStateListener可以處理還原視窗的事件,可以判斷一個視窗是不是在垂直和水平兩個方向都可以最大化(命令提示符視窗只可以在垂直方向上最大化),而這些都是WindowListener都無能為力
2.JLabel
JLabel是一標籤.在它的文字里嵌入html標籤,可以簡單實現一個超連結元件


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
class JLabelDemo
{
JFrame mainFrame;
JLabel simpleLabel;
public JLabelDemo() {
mainFrame = new JFrame ( "JLabelDemo" );
simpleLabel = new JLabel ("<html><a href=aaa>百度搜尋</a></html>");//嵌入了html標籤
simpleLabel.addMouseListener( new MouseAdapter(){//新增滑鼠事件偵聽器,當單擊標籤時,開啟網頁
public void mouseClicked( MouseEvent e ){
try{
Runtime.getRuntime().exec("cmd /c start http://www.baidu.com");
}catch( IOException ee ){
ee.printStackTrace();
}
}
});
simpleLabel.setCursor( new Cursor(Cursor.HAND_CURSOR) );//設定手形滑鼠
mainFrame.getContentPane().add( simpleLabel );//將標籤新增到視窗
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();//使視窗自動根據新增了的元件調整大小
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JLabelDemo();
}
}
[/code]
3.JButton
JButton是一個按鈕.它和JLabel一樣的簡單


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;

class JButtonDemo
{
JFrame mainFrame;
JButton simpleButton;
public JButtonDemo() {
mainFrame = new JFrame ( "JButtonDemo" );
simpleButton = new JButton("百度搜尋");
mainFrame.getContentPane().add( simpleButton );
simpleButton.addActionListener( new ActionListener(){//新增動作偵聽器,當按鈕被按下時執行這裡的程式碼以開啟網頁
public void actionPerformed( ActionEvent e){
try{
Runtime.getRuntime().exec("cmd /c start http://www.baidu.com");
}catch( IOException ee ){
ee.printStackTrace();
}
}
});
simpleButton.setCursor( new Cursor(Cursor.HAND_CURSOR) );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JButtonDemo();
}
}

[/code]
4.JTextField
一個文字框


[code]
package blog.swing;
import javax.swing.*;
import java.awt.event.*;

class JTextFieldDemo
{
JFrame mainFrame;
JTextField simpleTextField;
public JTextFieldDemo() {
mainFrame = new JFrame ( "JTextFieldDemo" );
simpleTextField = new JTextField(20);//構造寬度為20個字元的文字框
mainFrame.getContentPane().add( simpleTextField );
simpleTextField.addActionListener( new ActionListener(){//在輸入字元後按回車執行行程式碼,在標準輸出視窗輸出它的內容
public void actionPerformed( ActionEvent e){
System.out.println( simpleTextField.getText() );
}
});
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JTextFieldDemo();
}
}

[/code]
5.JTextArea
文字區域,與文字框不同的是它是多行的


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class JTextAreaDemo
{
JFrame mainFrame;
JTextArea simpleTextArea;
JButton appendButton;
public JTextAreaDemo() {
mainFrame = new JFrame ( "JTextAreaDemo" );
simpleTextArea = new JTextArea(10,20);//建立一個顯示10行20列的文字域
simpleTextArea.setLineWrap(true);//設定它自動換行
simpleTextArea.setWrapStyleWord(true);//設定它自動換行時根據單詞換行,而不是根據字元
appendButton = new JButton ("append text to the text area");
mainFrame.getContentPane().add( simpleTextArea,BorderLayout.PAGE_START );
mainFrame.getContentPane().add( appendButton,BorderLayout.PAGE_END );
appendButton.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
simpleTextArea.append("button appended text here");
System.out.println( simpleTextArea.getText() );
}
});
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JTextAreaDemo();
}
}

[/code]
6.JPasswordField

[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class JPasswordFieldDemo
{
JFrame mainFrame;
JPasswordField simplePasswordField;
public JPasswordFieldDemo() {
mainFrame = new JFrame ( "JPasswordFieldDemo" );
simplePasswordField = new JPasswordField(10);
simplePasswordField.setEchoChar('*');//設定要顯示的字元
mainFrame.getContentPane().add( simplePasswordField );
simplePasswordField.addActionListener( new ActionListener(){//回車時執行的動作
public void actionPerformed( ActionEvent e){
char[] input = simplePasswordField.getPassword();
for( char c : input )
System.out.print( c );
}
});
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JPasswordFieldDemo();
}
}

[/code]
7.JPanel
一個皮膚.一般用作控制元件的佈局.

[code]
package blog.swing;
import javax.swing.*;

class JPanelDemo
{
JFrame mainFrame;
JPanel simplePanel;
JButton simpleButton;
JLabel simpleLabel;
public JPanelDemo() {
mainFrame = new JFrame ( "JPanelDemo" );
simplePanel = new JPanel();
simpleButton = new JButton ("button");
simpleLabel = new JLabel ("label");
simplePanel.add( simpleLabel );
simplePanel.add( simpleButton );
mainFrame.getContentPane().add( simplePanel );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JPanelDemo();
}
}

[/code]
8.JCheckBox
核取方塊

[code]
package blog.swing;
import javax.swing.*;
import java.awt.event.*;

class JCheckBoxDemo implements ItemListener
{
JFrame mainFrame;
JPanel mainPanel;
JCheckBox simpleCheckBox1;
JCheckBox simpleCheckBox2;
public JCheckBoxDemo() {
mainFrame = new JFrame ( "JCheckBoxDemo" );
mainPanel = new JPanel ();
simpleCheckBox1 = new JCheckBox("checkbox1");
simpleCheckBox1.setMnemonic('1');
simpleCheckBox1.addItemListener(this);
simpleCheckBox2 = new JCheckBox("checkbox2");
simpleCheckBox2.setMnemonic('2');
simpleCheckBox2.addItemListener(this);
mainPanel.add(simpleCheckBox1);
mainPanel.add(simpleCheckBox2);
mainFrame.getContentPane().add( mainPanel );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public void itemStateChanged( ItemEvent e ){
JCheckBox cb = (JCheckBox)e.getSource();
if( cb== simpleCheckBox1 )
System.out.println( "simpleCheckBox1" );
else
System.out.println( "simpleCheckBox2" );
}
public static void main(String[] args)
{
new JCheckBoxDemo();
}
}

[/code]
9.JRadioButton
單選按鈕.單選按鈕要用到ButtonGroup.新增到同一個ButtonGroup的單選按鈕表示在它們之間只可選其一.不同ButtonGroup裡的單選按鈕相互之間的選擇不受影響.

[code]
package blog.swing;
import javax.swing.*;
import java.awt.event.*;

class JRadioButtonDemo implements ItemListener
{
JFrame mainFrame;
JPanel mainPanel;
ButtonGroup buttonGroup;
JRadioButton simpleRadioButton1;
JRadioButton simpleRadioButton2;
public JRadioButtonDemo() {
mainFrame = new JFrame ( "JRadioButtonDemo" );
mainPanel = new JPanel ();
simpleRadioButton1 = new JRadioButton("RadioButton1");
simpleRadioButton1.setMnemonic('1');
simpleRadioButton1.addItemListener(this);
simpleRadioButton2 = new JRadioButton("RadioButton2");
simpleRadioButton2.setMnemonic('2');
simpleRadioButton2.addItemListener(this);
buttonGroup = new ButtonGroup();
buttonGroup.add(simpleRadioButton1);
buttonGroup.add(simpleRadioButton2);
mainPanel.add(simpleRadioButton1);
mainPanel.add(simpleRadioButton2);
mainFrame.getContentPane().add( mainPanel );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public void itemStateChanged( ItemEvent e ){
JRadioButton cb = (JRadioButton)e.getSource();
if( cb== simpleRadioButton1 )
System.out.println( "simpleRadioButton1" );
else
System.out.println( "simpleRadioButton2" );
}
public static void main(String[] args)
{
new JRadioButtonDemo();
}
}

[/code]
10.JScrollPane
JScrollPane由四個角,兩個頭部,和一個視口組成.四個角和兩個頭部都是由Component組成.四個角並不是總是顯示出來的.左上角只有當兩個頭部同時存在才顯示,右下角只有兩個滾動條同時出現才會出現.其他兩個角可同理知道什麼時候會出現.視口是顯示內容的部分,由JViewport物件表示.而真正顯示的內容,由JViewport的view表示

[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class JScrollPaneDemo
{
JFrame mainFrame;
JScrollPane simpleScrollPane;
JTextArea simpleTextArea;
JButton changeViewport;
public JScrollPaneDemo() {
mainFrame = new JFrame ( "JScrollPaneDemo" );
simpleTextArea = new JTextArea(10,20);
simpleScrollPane = new JScrollPane( simpleTextArea );//建立一個滾動窗格,裡面顯示的內容是文字區域
simpleScrollPane.setRowHeaderView( new JLabel ("this is a row header") );//設定行標題
simpleScrollPane.setColumnHeaderView( new JLabel ("this is a column header") );//設定列標題
simpleScrollPane.setCorner( JScrollPane.LOWER_RIGHT_CORNER,new JButton("corner") );//設定右下角
simpleScrollPane.setCorner( JScrollPane.UPPER_LEFT_CORNER,new JButton("corner") );//設定左上角
changeViewport = new JButton ("changeViewport");
changeViewport.addActionListener( new ActionListener(){//當單擊按鈕時,滾動視窗顯示的內容變為另一個文字區域
public void actionPerformed( ActionEvent e){
simpleScrollPane.getViewport().setView( new JTextArea("changeViewpot") );
}
});
mainFrame.getContentPane().add( simpleScrollPane,BorderLayout.PAGE_START );
mainFrame.getContentPane().add( changeViewport,BorderLayout.PAGE_END );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JScrollPaneDemo();
}
}

[/code]
現在開始講相對複雜一點的元件
11.JList
JList是一個列表.這裡將首次引入Model這個概念,中文翻譯是模型,不好理解,其實就是資料的意思.JList用ListModel儲存它的資料.簡單應用可以用實現了ListModel的AbstraceListModel的子類DefaultListModel來儲存它的資料(儘管它的名字有Default,但是隻有你使用了它建立JList,它才存在.即如果你沒有用DefaultListModel建立JList,則你用getModel()返回的ListModel不能強制轉換為DefaultListModel).
很多元件的Model都有這種結構,即 XXXModel--AbstractXXXModel--DefaultXXXModel
下面講一下DefaultListModel,它的方法基本上和Vector<E>一樣,另外新增了一個Object getElementAt(int index)
新增元素: void add(int index, Object element),void addElement(Object obj),void insertElementAt(Object obj, int index)
刪除元素: Object remove(int index),boolean removeElement(Object obj),void removeElementAt(int index),
void removeAllElements(),void removeRange(int fromIndex, int toIndex),void clear()
查詢元素: Object elementAt(int index),Object get(int index),Object getElementAt(int index), Object firstElement(),Object lastElement()
修改元素: Object set(int index, Object element),void setElementAt(Object obj, int index)
JList自身沒有對單個元素處理的方法,只有void setListData(Object[] listData),void setListData(Vector<?> listData),void setModel(ListModel model)
來設定全部元素的方法
當要對單個元素進行處理時,用ListModel getModel()返回Model後,再對Model操作
通過void addListDataListener(ListDataListener l)可以在ListModel被修改時被通知
和JList相關的還有ListSelectionModel,它管理JList的選擇項.它沒有AbstractListSelectionModel這個子類,而直接有一個DefaultListSelectionModel這個實現類,
JList預設也是使用的這個實現類. 和上面講的DefaultListModel不同,這個Model不用你自己建立就已存在.
通過void addListSelectionListener(ListSelectionListener x)可以在選擇改變時被通知.
void setSelectionMode(int selectionMode)可以設定多選(待續或非連續)或是單選
DefaultListSelectionModel沒有返回選擇了的元素的方法,它只負責去選擇哪些項
修改選擇項的方法:
void addSelectionInterval(int index0, int index1),
void removeSelectionInterval(int index0, int index1)
void setSelectionInterval(int index0, int index1)
void clearSelection()
下面這兩個方法在ListModel被更改時更改選擇項會更方便,因為不用根據ListModel的變動計算索引
void removeIndexInterval(int index0, int index1)
void insertIndexInterval(int index, int length, boolean before)
另外的一些方法
int getMaxSelectionIndex(),int getMinSelectionIndex()
boolean isSelectedIndex(int index),boolean isSelectionEmpty()
很多在DefaultListSelectionModel裡的方法,在JList自身裡也有.例如上面的XXXSelectionInnterval(...)和addListSelectionListener(...)
另外它還有:
int getSelectedIndex(),int[] getSelectedIndices()
Object getSelectedValue(), Object[] getSelectedValues()
void setSelectedIndex(int index),void setSelectedIndices(int[] indices)
void setSelectedValue(Object anObject, boolean shouldScroll)
最後一個內容是,自定義JList
預設JList顯示的內容是String.在建立它的時候,如果你把其他非String的物件傳給它要它顯示,它會呼叫toString,然後顯示返回的String.
通過void setCellRenderer(ListCellRenderer cellRenderer)可以自定義JList顯示內容的型別.
引數是一個"渲染器".很多元件在自定義的時候都是用渲染器來實現的.它只一個方法:
Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
下面舉例說明一下它如何工作:假設你呼叫了setCellRenderer,而且把"label"這個String傳給JList要它顯示.那麼"label"這個值就會傳給上面這個方法的value這個值.
這時你可以用"label"構造一個元件,然後返回.例如,你可以JLabel label = new JLabel( (String)value ); return label.這樣,在JList就會顯示一個JLabel了.

[code]
package blog.swing;
import java.awt.*;
import javax.swing.event.*;
import javax.swing.*;
class JListCustomDemo
{
JFrame mainFrame;
JList simpleList;
public JListCustomDemo(){
mainFrame = new JFrame ("JListCustomDemo");

final DefaultListModel model = new DefaultListModel();
model.addElement("button1");
model.addElement("button2");
simpleList = new JList(model);
simpleList.setCellRenderer( new CustomListCellRenderer() );

simpleList.addListSelectionListener( new ListSelectionListener(){
public void valueChanged( ListSelectionEvent e){
System.out.println( model.getElementAt( simpleList.getSelectedIndex() ) );
}
});

mainFrame.add(simpleList);
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setLocationRelativeTo(null);
mainFrame.pack();
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JListCustomDemo();
}
}
class CustomListCellRenderer implements ListCellRenderer{
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus
){
return new JButton( (String)value );
}

}


[/code]
[code]
package blog.swing;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class JListDemo
{
JFrame mainFrame;
JList simpleList;
JButton changeSelections;
public JListDemo() {
mainFrame = new JFrame ( "JListDemo" );
/* Vector<String> listData = new Vector<String>();
listData.add("data1");
listData.add("data2");
listData.add("data3");
listData.add("data4");
simpleList = new JList( listData );
*/
DefaultListModel dlm = new DefaultListModel();
dlm.addElement("data1");
dlm.addElement("data2");
dlm.addElement("data3");
dlm.addElement("data4");
simpleList = new JList( dlm );
changeSelections = new JButton ("changeSelections");
changeSelections.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
DefaultListSelectionModel dlsm = (DefaultListSelectionModel)simpleList.getSelectionModel();
//dlsm.addSelectionInterval(0,1);
//dlsm.removeSelectionInterval(0,1);
dlsm.setSelectionInterval(0,1);
/* DefaultListModel dlm = (DefaultListModel)simpleList.getModel();
dlm.remove(0);
dlm.remove(1);
*/
}
});
mainFrame.getContentPane().add( simpleList,BorderLayout.PAGE_START );
mainFrame.getContentPane().add( changeSelections,BorderLayout.PAGE_END );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JListDemo();
}
}

[/code]
12.JComboBox
組合框和JList很相似,它們都是用ListModel來儲存資料.預設它是使用實現了ListModel的子介面ComboBoxModel的DefaultComboBoxModel來儲存資料的.與JList的情況不同,一個JComboBox總是有一個Model來儲存資料的,而JList則不然.
DefaultComboBoxModel的方法:
新增元素:addElement(Object object),insertElementAt(Object object,int index)
刪除元素:removeElement(Object object),removeElementAt(int index),removeAllElements()
獲取元素:getElementAt(int index)
和選擇有關的:getSelectedItem(),setSelectedItem(Object object)
此外還有getSize(),getIndexOf(Object object)
JComboBox自身也有一些處理項的方法:
void addItem(Object anObject),void insertItemAt(Object anObject, int index)
void removeItem(Object anObject),void removeItemAt(int anIndex),void removeAllItems()
Object getItemAt(int index)
int getItemCount()
以上基本上是把DefaultComboBoxModel裡的方法的Element改為Item
int getSelectedIndex(),Object getSelectedItem(),Object[] getSelectedObjects()
通過在JComboBox上新增ActionListener,可以在選擇改變了的時候作出響應.
最後是自定義組合框.通過呼叫和JList一樣的void setRenderer(ListCellRenderer aRenderer) 就可以自定義組合框.
下面的例子示範了在JComboBox裡顯示圖片

[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;

class JComboBoxDemo
{
JFrame mainFrame;
JComboBox simpleComboBox;
public JComboBoxDemo() {
mainFrame = new JFrame ( "JComboBoxDemo" );
Vector<String> cbData = new Vector<String>();
cbData.add("images/Pig.gif");
cbData.add("images/Bird.gif");
cbData.add("images/Dog.gif");
cbData.add("images/Cat.gif");
simpleComboBox = new JComboBox( cbData);
simpleComboBox.setPreferredSize( new Dimension(200,130) );
simpleComboBox.setMaximumRowCount(2);
simpleComboBox.setRenderer( new CustomComboBoxRenderer() );
mainFrame.getContentPane().add( simpleComboBox );
simpleComboBox.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
System.out.println( "selection changed" );
System.out.println( simpleComboBox.getSelectedItem() );
}
});
simpleComboBox.setCursor( new Cursor(Cursor.HAND_CURSOR) );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}

public static void main(String[] args)
{
new JComboBoxDemo();
}

class CustomComboBoxRenderer extends JLabel implements ListCellRenderer{
CustomComboBoxRenderer(){
setOpaque(true);
setHorizontalAlignment(CENTER);
setVerticalAlignment(CENTER);

}
public Component getListCellRendererComponent(
JList list,
Object value,
int index,
boolean isSelected,
boolean cellHasFocus)
{
if (isSelected) {
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
String imageFileName = (String)value;
ImageIcon labelIcon = new ImageIcon( imageFileName );
setText( imageFileName.substring(imageFileName.lastIndexOf('/')+1) );
setIcon( labelIcon );
return this;
}
}
}
[/code]
13.JFileChooser
JFileChooser代表一個開啟/儲存檔案對話方塊
三個較簡單的建構函式:
JFileChooser(),JFileChooser(File currentDirectory),JFileChooser(String currentDirectoryPath)
構造物件以後,呼叫int showOpenDialog(Component parent)或int showSaveDialog(Component parent)顯示開啟/儲存對話方塊
呼叫int showDialog(Component parent, String approveButtonText) 顯示自定義開啟/儲存按鈕文字的對話方塊
三個方法的返回值都是整型.當按下開啟/儲存時,返回APPROVE_OPTION,否則返回CANCEL_OPTION
可以用javax.swing.filechooser.FileFilter來過濾不需要顯示的檔案.它只有兩個方法
boolean accept(File f) 通過通過判斷f的字尾來決定顯示與否.要顯示則返回true,否則返回false
String getDescription() 返回對這個過濾器的描述
和FileFilter有關的方法:
void setFileFilter(FileFilter filter),void addChoosableFileFilter(FileFilter filter)
當我們選擇的檔案改變(但是未按下開啟或儲存按鈕)時,會有java.beans.PropertyChangeEvent產生
通過void addPropertyChangeListener(PropertyChangeListener listener)可以對此事件進行偵聽
PropertyChangeEvent的方法有:
Object getNewValue(), Object getOldValue(), String getPropertyName()
Object getPropagationId(),void setPropagationId(Object propagationId)
通過void setAccessory(JComponent c)可以向JFileChooser新增自定義的部分.
其他有用的方法:
File getSelectedFile(),File[] getSelectedFiles()
void setFileSelectionMode(int):FILES_ONLY,DIRECTORIES_ONLY,FILES_AND_DIRECTORIES
void setMultiSelectionEnabled(boolean),setAcceptAllFileFilterUsed(boolean)
void setCurrentDirectory(File) ,void setFileHidingEnabled(boolean)


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.File;
import java.beans.*;

class JFileChooserDemo
{
JFileChooser simpleFileChooser;
JScrollPane previewScrollPane;
JLabel previewLabel;
public JFileChooserDemo() {
simpleFileChooser = new JFileChooser();
previewLabel = new JLabel ();
previewLabel.setHorizontalAlignment(SwingConstants.CENTER);
previewScrollPane = new JScrollPane ( previewLabel );
previewScrollPane.setPreferredSize(new Dimension(100,10));
simpleFileChooser.setAccessory( previewScrollPane );
simpleFileChooser.addChoosableFileFilter( new GifFileFilter() );
simpleFileChooser.addChoosableFileFilter( new PngFileFilter() );
simpleFileChooser.addChoosableFileFilter( new JpgFileFilter() );
simpleFileChooser.addPropertyChangeListener( new PropertyChangeListener(){
public void propertyChange( PropertyChangeEvent e ){
if ( JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals( e.getPropertyName() ) ){
File newSelectedFile = (File)e.getNewValue();
if( newSelectedFile != null){
ImageIcon icon = new ImageIcon( newSelectedFile.getPath() );
previewLabel.setIcon( icon );
}
}
}
});
simpleFileChooser.showOpenDialog(null);
//simpleFileChooser.showDialog(null,"自定義按鈕文字");
}
class GifFileFilter extends FileFilter{
public boolean accept( File f ){
return f.getName().endsWith(".gif");
}
public String getDescription(){
return "Gif files(.gif)";
}
}
class PngFileFilter extends FileFilter{
public boolean accept( File f ){
return f.getName().endsWith(".png");
}
public String getDescription(){
return "Png files(.png)";
}
}
class JpgFileFilter extends FileFilter{
public boolean accept( File f ){
return f.getName().endsWith(".jpg");
}
public String getDescription(){
return "Jpg files(.jpg)";
}
}
public static void main(String[] args)
{
new JFileChooserDemo();
}
}
[/code]
14.JColorChooser
一個顏色選擇器.它的構造方法有:
JColorChooser(),JColorChooser(Color initialColor),JColorChooser(ColorSelectionModel model)
建立了物件以後,可以呼叫將它新增到JFrame,JPanel等其他容器裡面.
也可呼叫它的靜態方法static Color showDialog(Component component, String title, Color initialColor )來建立一個模態的對話方塊.
它用ColorSelectionModel來管理選擇的顏色.通過呼叫它的void addChangeListener(ChangeListener listener)可以在選擇的顏色變化時作出反應.
呼叫void setSelectedColor(Color color)更改選擇的顏色,Color getSelectedColor()取得選擇的顏色
JColorChooser自身的獲取顏色的方法是Color getColor().
JColorChooser由顏色選擇皮膚和預覽皮膚組成,所以自定義它,就是對這兩部分作文章
void setPreviewPanel(JComponent) 可以設定預覽皮膚.setPreviewPanel( new JPanel() )可以移除預覽皮膚,將引數設為null,即setPreviewPanel(null)可以將預覽皮膚設回預設.
void setChooserPanels(AbstractColorChooserPanel[])和void addChooserPanel(AbstractColorChooserPanel)分別可以設定和新增顏色選擇皮膚
void removeChooserPanel(AbstractColorChooserPanel)可以刪除顏色選擇皮膚
AbstractColorChooserPanel代表差一個顏色選擇皮膚,它在javax.swing.colorchooser包裡.它有五個抽象方法,而其中兩個是目前不用的.所以只需定義下面三個:
String getDisplayName()皮膚顯示的文字.
void buildChooser() 負責建立一個顏色選擇皮膚
void updateChooser() 負責更新顯示顏色皮膚


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;

class JColorChooserDemo
{
JFrame mainFrame;
JColorChooser simpleColorChooser;
JLabel sampleLabel;
public JColorChooserDemo() {
mainFrame = new JFrame ( "JColorChooserDemo" );
sampleLabel = new JLabel ("sample");
simpleColorChooser = new JColorChooser();
simpleColorChooser.getSelectionModel().addChangeListener( new ChangeListener(){
public void stateChanged( ChangeEvent e ){
sampleLabel.setForeground( simpleColorChooser.getColor() );
}
});
mainFrame.getContentPane().add( simpleColorChooser,BorderLayout.PAGE_START );
mainFrame.getContentPane().add( sampleLabel,BorderLayout.PAGE_END );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JColorChooserDemo();
}
}

[/code]
[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.colorchooser.*;
class JColorChooserCustomDemo
{
JFrame mainFrame;
JColorChooser simpleColorChooserCustom;
JLabel sampleLabel;
public JColorChooserCustomDemo() {
mainFrame = new JFrame ( "JColorChooserCustomDemo" );
sampleLabel = new JLabel ("sample");
simpleColorChooserCustom = new JColorChooser();
simpleColorChooserCustom.getSelectionModel().addChangeListener( new ChangeListener(){
public void stateChanged( ChangeEvent e ){
sampleLabel.setForeground( simpleColorChooserCustom.getColor() );
}
});
AbstractColorChooserPanel accps[] = { new CustomColorChooserPanel(),
new CustomColorChooserPanel()};
simpleColorChooserCustom.setChooserPanels(accps);
mainFrame.getContentPane().add( simpleColorChooserCustom,BorderLayout.PAGE_START );
mainFrame.getContentPane().add( sampleLabel,BorderLayout.PAGE_END );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
class CustomColorChooserPanel extends AbstractColorChooserPanel implements ActionListener{
JButton redButton;
JButton greenButton;
JButton blueButton;
public CustomColorChooserPanel(){
this.redButton = new JButton("red");
this.greenButton = new JButton("green");
this.blueButton = new JButton("blue");
redButton.addActionListener(this);
greenButton.addActionListener(this);
blueButton.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {
if((JButton)ae.getSource() == redButton){
getColorSelectionModel().setSelectedColor(Color.red);
}else{
if((JButton)ae.getSource() == greenButton){
getColorSelectionModel().setSelectedColor(Color.green);
}
else{
getColorSelectionModel().setSelectedColor(Color.blue);
}
}
}
public void buildChooser(){
add(redButton);
add(greenButton);
add(blueButton);
}
public void updateChooser(){}
public String getDisplayName(){
return "CustomPanel";
}
public Icon getSmallDisplayIcon() {
return null;
}
public Icon getLargeDisplayIcon() {
return null;
}
}
public static void main(String[] args)
{
new JColorChooserCustomDemo();
}
}
[/code]
15.JSlider
JSlider是一個滑動條.其實它還是比較容易使用的
構造方法比較多:
JSlider(),JSlider(int orientation),JSlider(int min, int max)
JSlider(int min, int max, int value) ,JSlider(int orientation, int min, int max, int value)
通過void addChangeListener(ChangeListener l) 可以在它的值改變時作出反應
最需要操作的是它的刻度.下面是和刻度有關的方法:
void setMajorTickSpacing(int n),void setMinorTickSpacing(int n) ,void setLabelTable(Dictionary labels)
void setPaintLabels(boolean b),void setPaintTicks(boolean b)
另外一些常用方法:
setValue(int n),void setOrientation(int orientation),void setMinimum(int minimum),void setMaximum(int maximum)
int getValue() ,int getOrientation()


[code]
package blog.swing;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;

class JSliderDemo
{
JFrame mainFrame;
JSlider simpleSlider;
public JSliderDemo() {
mainFrame = new JFrame ( "JSliderDemo" );
simpleSlider = new JSlider(SwingConstants.VERTICAL);

Hashtable sliderLabelHashTable = simpleSlider.createStandardLabels(10);
for(int i=0; i<sliderLabelHashTable.size()*10; i+=10){
sliderLabelHashTable.put(new Integer(i),new JLabel("label " + i));
}
simpleSlider.setLabelTable(sliderLabelHashTable);
simpleSlider.setPaintLabels(true);
simpleSlider.setMinorTickSpacing(5);
simpleSlider.setMajorTickSpacing(10);
simpleSlider.setPaintTicks(true);

mainFrame.getContentPane().add( simpleSlider );
simpleSlider.addChangeListener( new ChangeListener(){
public void stateChanged( ChangeEvent e){
System.out.println( simpleSlider.getValue() );
}
});
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JSliderDemo();
}
}
[/code]
16.JLayeredPane
JFrame,JApplet,JDialog,JInternalFrame其實是由好幾部分組成的
JFrame,JApplet,JDialog,JInternalFrame
|__JRootPane:根層
|__GlassPane(Component):GlassPane是用元件實現的,沒有JGlassPane
|__JLayeredPane:分層.在這裡可以定義元件的疊放次序
|__ContentPane:ContentPane和GlassPane一樣,只一個抽象層,沒有對應的類.在它們上面可以放元件
|__JMenuBar
但是,我們一般不直接使用JRootPane的JLayeredPane,而是自己定義一個.
它只有一個構造方法,無參的JLayeredPane()
用Component add(Component comp, int index)將元件新增到其上並指定層級,層級大的元件顯示在小的上面.
以後可以動態改變所在層:
void moveToBack(Component c),void moveToFront(Component c):這兩個方法改變的是層內的位置,而不是層間的位置
void setPosition(Component c, int position):設定層內的位置.0表示最上面,-1表示最下面
void setLayer(Component c, int layer)
void setLayer(Component c, int layer, int position) 設定元件的層級,position是指在層內的位置.


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;

class JLayeredPaneDemo
{
JFrame mainFrame;
JLayeredPane layeredPane;
JLabel blackLabel;
JComboBox layerList;
public JLayeredPaneDemo() {
mainFrame = new JFrame ( "JLayeredPaneDemo" );
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize( new Dimension(200,300) );
Color[] colors = { Color.red, Color.green, Color.yellow, Color.blue };
for( int i=0; i<4; i++){
JLabel label = createLabel(i,colors[i]);
layeredPane.add( label, new Integer(i) );
}
blackLabel = new JLabel ( "lll" );
blackLabel.setBounds( 15,40,120,120);
blackLabel.setOpaque( true );
blackLabel.setBackground( Color.black );
layeredPane.add( blackLabel, new Integer(1), 0 );
layeredPane.addMouseMotionListener( new MouseInputAdapter(){
public void mouseMoved( MouseEvent e ){
blackLabel.setBounds( e.getX(),e.getY(),120,120 );
}
} );

String layerListItem[] = { "PUT THE BLACK LABEL AT LAYER 0",
"PUT THE BLACK LABEL AT LAYER 1","PUT THE BLACK LABEL AT LAYER 2",
"PUT THE BLACK LABEL AT LAYER 3","PUT THE BLACK LABEL AT LAYER 4" };
layerList = new JComboBox( layerListItem );
layerList.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
layeredPane.setLayer( blackLabel,layerList.getSelectedIndex() );
}
} );
mainFrame.getContentPane().add( layerList ,BorderLayout.PAGE_END);
mainFrame.getContentPane().add( layeredPane, BorderLayout.PAGE_START);
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setSize( 400,400 );
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
JLabel createLabel(int i,Color color){
JLabel label = new JLabel ( ""+i);
label.setOpaque( true );
label.setBounds( i*60,i*60,140,140 );
label.setBackground( color );
return label;
}
public static void main(String[] args)
{
new JLayeredPaneDemo();
}
}
[/code]
17.JInternalFrame
JFrame不能新增JFrame到自已的內容皮膚.那麼,如何實現多文件程式呢?用JInternalFrame可以實現.
一般的做法是,把JInternalFrame新增到JDesktopPane,然後把JDesktopPane作為JFrame的內容皮膚(ContentPane)
JInternalFrame(String title[, boolean resizable[, boolean closable[, boolean maximizable[, boolean iconifiable]]]])
[]裡面的表示可以省略


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;

class JInternalFrameDemo
{
JFrame mainFrame;
JDesktopPane desktop;
public JInternalFrameDemo(){
mainFrame = new JFrame ("JInternalFrame");
desktop = new JDesktopPane();

for(int i=0; i<4; i++){
JInternalFrame internalFrame = new JInternalFrame();
internalFrame.setVisible( true );
internalFrame.setLocation(i*40,i*40);
internalFrame.getContentPane().add( new JButton ("button") );
internalFrame.pack();
desktop.add(internalFrame);
}
// desktop.setDragMode(JDesktopPane.LIVE_DRAG_MODE);
desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
mainFrame.setContentPane(desktop);
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setSize(400,400);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}

public static void main(String[] args)
{
new JInternalFrameDemo();
}
}
[/code]
18.GlassPane
GlassPane可以用來截獲輸入事件(鍵盤和滑鼠).沒有JGlassPane
可以呼叫JFrame的void setGlassPane(Component glassPane)來設定GlassPane
預設GlassPane是不可見的,要呼叫getGlassPane().setVisible(true)使其可見


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;

class GlassPaneDemo
{
JFrame mainFrame;
JPanel mainPanel;
JButton button;
public GlassPaneDemo() {
mainFrame = new JFrame ( );
mainPanel = new JPanel ();
button = new JButton ("button");
//mainFrame.setGlassPane( mainPanel );
mainPanel.add( button );
mainFrame.getContentPane().add( mainPanel );
mainFrame.setGlassPane( new MyGlassPane() );
mainFrame.getGlassPane().setVisible( true );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.setSize( 300,400 );
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
private class MyGlassPane extends JComponent {
Point point = new Point(10,10);
public MyGlassPane(){
addMouseListener( new MouseAdapter(){
public void mouseClicked( MouseEvent e ){
point = new Point( e.getX(),e.getY() );
repaint();
}
} );
}
public void paintComponent( Graphics g ){
g.setColor( Color.red );
g.fillOval( point.x,point.y,20,20 );
}
}
public static void main(String[] args)
{
SwingUtilities.invokeLater( new Runnable(){
public void run(){
new GlassPaneDemo();
}
});
}
}
[/code]
19.JProgressBar
進度條.當一個任務要較長時間來完成時,我們可以用一個進度條來表示任務的完成進度.
在講進度條的用法之前,我們先來看javax.swing.SwingWorker類的用法.我們將用這個類來模擬我們的"較長的任務".
在java中,元件是在一個使用者介面線各里繪製的.如果我們把一個用時較長的任務放到這個執行緒來實現(例如我們把一個用時較長的任務放到一個按鈕的
actionPerformed(...)),那麼使用者介面將會僵死(例如包含那個按鈕的視窗的選單將暫不可用,而要等actionPerform完成返回後才可用).
通過SwingWorker,我們可以把這個較長的任務放到另外一個執行緒來實現,這樣使用者介面就不會僵死了.
這個SwingWorker是jdk1.6才引進的,.之前也有一個SwingWorker.但是它們有所不同:舊的SwingWorker是可重用的,而新的不能;另外它們的方法的名字也不一樣.
SwingWorker主要有六個方法doInBackground,get,done,publish,process,execute
SwingWorker是一個泛型類,有兩個型別引數.第一型別引數就是doInBackground和get的返回值的型別,而第二個型別引數是publish的形參型別.......
我們的較長任務是在doInBackground裡完成的,doInBackground的返回值可以用get取得.get有無參和無參兩個版本,引數代表的是等待doInBackground完成的時間,無參表示直到doInBackground完成,get才返回.
get要等到doInBackground完成才知道任務完成情況.怎麼了解任務的執行過程呢?publish可以做到這一點.publish的引數個數是任意的,但是,每一個引數的型別都必須是SwingWorker的第二個型別引數指定的型別.
我們用publish向外界釋出任務執行的情況,而用process來收集這些情況.process是在事件分發執行緒中執行的.在它被執行之前,SwingWorker的publish可能已經執行多次,所以process的引數是一個List,這樣就可以包含所有publish了的情況.
done是在doInBackground執行完成之後執行的.
execute是使doInBackground開始執行.
以上的方法只有doInBackground是必須自己實現的,其他都是可選的.
下面是一個例子.在這個例子中有兩個按鈕.第一個按鈕使SwingWorker開始工作,第二個按鈕呼叫get方法取得doInBackground的返回值.
在SwingWorker開始工作以後但是還沒有結束前按下第二個按鈕,可以看到介面僵死了,這是因為我們在按鈕的actionPerformed(在事件分發執行緒裡呼叫)裡呼叫了get,而無參的get在doInBackground返回前是不會返回的.
在doInBackground完成之後,我們再按下第一個按鈕,程式並沒有變化.這是因為SwingWorker是不可重用的.所以我們用匿名內部類來實現我們的SwingWorker.
在程式中我們還用到了publish和process.在process中,我們輸出publish的結果.按下第二個按鈕之前,process每次只輸出一個值,而在doInBackground返回之前按下第二個按鈕,因為process是在事件分發執行緒裡執行的,而get阻塞了事件分發執行緒,所以process不再輸出了,而是等到最後連續輸出數個值.


[code]
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.util.concurrent.ExecutionException;

class SwingWorkerTest
{
JFrame mainFrame;
JPanel mainPanel;
JButton button;
JButton getButton;
public SwingWorkerTest() {
mainFrame = new JFrame ( );
mainPanel = new JPanel ();
final javax.swing.SwingWorker<Integer,Integer> worker =
new javax.swing.SwingWorker<Integer,Integer>(){
public Integer doInBackground(){
int coutn = 0;
while( (coutn++)<10 ){
try{
System.out.println( "doInBackground() is doing a long job" );
Thread.sleep(1000);
publish( new Integer( (int)(Math.random()*1000) ) );
}catch( InterruptedException e ){
e.printStackTrace();
}
}
return new Integer(3);
}
@Override
public void process(List<Integer> integers){
int i = 0;
Iterator iterator = integers.iterator();
while( iterator.hasNext() ){
i++;
Integer integer = (Integer)iterator.next();
System.out.println( "在process輸出publish的值"+i+" "+integer );
}
}
};
button = new JButton ("start");
button.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
worker.execute();
}
});
getButton = new JButton ("Get");
getButton.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
try{
System.out.println( "doInBackground的返回值: "+worker.get() );
}catch( InterruptedException ie ){
ie.printStackTrace();
}catch( ExecutionException ee ){
ee.printStackTrace();
}
}
});
mainPanel.add(button);
mainPanel.add(getButton);
mainFrame.getContentPane().add( mainPanel );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new SwingWorkerTest();
}
}
[/code]
除了用JProgressBar來顯示進度,我們還可以用ProgressMonitor來實現.
ProgressMonitor提供了建立進度條的簡便方法,它顯示的進度條出現在一個對話方塊裡
它只有一個構造方法:ProgressMonitor(Component parentComponent, Object message, String note, int min, int max)
message和note引數都是和進度條一起顯示在對話方塊裡,不同的是,note是可變的,而message不可以.min和max是進度的最小值和最大值
這個對話方塊並不是在任務一開始就顯示出來的,而是等500個百萬分之一秒再出來,這個"500"可以用void setMillisToPopup(int millisToPopup)來設定,引數的單位是百萬分之一秒;而且,如果它計算得知這個任務用時不超過2000個百萬分之一秒,那麼這個對話方塊就永遠不會出來.這個"2000",可以用void setMillisToDecideToPopup(int)來設定,引數的單位也是百萬分之一秒
它其他的方法有:
int getMillisToPopup()
void setMinimum(int m),void setMaximum(int m),void setNote(String note),void setProgress(int nv)
int getMinimum() , int getMaximum() ,String getNote() ,沒有int getProgress()
boolean isCanceled()
這裡再介紹SwingWorker的幾個方法:
setProgress:設定任務的進度
getProgress:得到任務的進度
可以用addPropertyChangeListener(PropertyChangeLitener)對上面兩個方法的呼叫作出響應
cancel(boolean):取消任務
isCancelled():判斷任務是否已被取消
下面是一個例子.


[code]
package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Random;
import java.beans.*;

class ProgressMonitorDemo
{
JFrame mainFrame;
ProgressMonitor simpleProgressMonitor;
JButton startButton;
Worker worker;
public ProgressMonitorDemo() {
mainFrame = new JFrame ( "ProgressMonitorDemo" );
startButton = new JButton ("Start");
startButton.addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e){
simpleProgressMonitor = new ProgressMonitor(mainFrame,"正在執行任務","",0,100);
simpleProgressMonitor.setMillisToDecideToPopup(0);
simpleProgressMonitor.setMillisToPopup(0);
worker = new Worker();
worker.addPropertyChangeListener( new PropertyChangeListener(){
public void propertyChange( PropertyChangeEvent e ){
if( "progress".equals( e.getPropertyName() )){
int progress = (Integer)e.getNewValue();
simpleProgressMonitor.setProgress( progress );
String message = String.format("%d%% completed",progress);
simpleProgressMonitor.setNote(message);
}
}
});
worker.execute();
startButton.setEnabled(false);
}
} );
mainFrame.getContentPane().add( startButton,BorderLayout.LINE_START );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}

public static void main(String[] args)
{
new ProgressMonitorDemo();
}
class Worker extends javax.swing.SwingWorker<Void,Void>{
public Void doInBackground(){
int progress = 0;
Random r = new Random();
while( progress<=100 && !isCancelled() ){
progress += r.nextInt(10);
setProgress( Math.min(progress,100) );
try{
Thread.sleep( r.nextInt(1000) );
}catch( InterruptedException e ){
e.printStackTrace();
}
}
return null;
}
public void done(){
startButton.setEnabled(true);
}
}
}
[/code]
20.JTabbedPane
選項卡.
構造方法:JTabbedPane() ,JTabbedPane(int tabPlacement) ,JTabbedPane(int tabPlacement, int tabLayoutPolicy)
新增選項卡:
void addTab(String title, Component component)
void addTab(String title, Icon icon, Component component)
void addTab(String title, Icon icon, Component component, String tip)
void insertTab(String title, Icon icon, Component component, String tip, int index)
刪除選項卡:
void remove(int index)
void removeAll()
void removeTabAt(int index)
修改選項卡上顯示的元件:
void setComponentAt(int index, Component component)
Component getComponentAt(int index)
設定外觀:
void setTabPlacement(int tabPlacement):JTabbedPane.TOP, JTabbedPane.BOTTOM ,JTabbedPane.LEFT,JTabbedPane.RIGHT
void setTabLayoutPolicy(int tabLayoutPolicy) :JTabbedPane.WRAP_TAB_LAYOUT ,JTabbedPane.SCROLL_TAB_LAYOUT
void setTitleAt(int index, String title)
void setToolTipTextAt(int index, String toolTipText)
void setIconAt(int index, Icon icon)
void setBackgroundAt(int index, Color background)
void setForegroundAt(int index, Color foreground)
查詢選項卡:
int indexAtLocation(int x, int y)
int indexOfComponent(Component component)
int indexOfTab(Icon icon)
int indexOfTab(String title)
和選擇有關的:
int getSelectedIndex()
void setSelectedIndex(int index)
Component getSelectedComponent()
void setSelectedComponent(Component c)
自定義標籤上的元件:
void setTabComponentAt(int index, Component c);
Component getTabComponentAt(int index);


[code]
package blog.swing;
import javax.swing.*;
import java.awt.Color;
class JTabbedPaneDemo
{
JFrame mainFrame;
JTabbedPane simpleTabbedPane;
public JTabbedPaneDemo() {
mainFrame = new JFrame ( "JTabbedPaneDemo" );
simpleTabbedPane = new JTabbedPane();
simpleTabbedPane.setTabLayoutPolicy( JTabbedPane.SCROLL_TAB_LAYOUT );
simpleTabbedPane.addTab("Tab1",new JLabel ("Component1"));
simpleTabbedPane.addTab("Tab2",new JLabel ("Component2"));
simpleTabbedPane.addTab("Tab3",new JLabel ("Component3"));
simpleTabbedPane.addTab("Tab4",new JLabel ("Component4"));
for(int i=0; i<4; i++){
simpleTabbedPane.setTabComponentAt( i,new JButton (""+i));
simpleTabbedPane.setBackgroundAt(i,Color.white);
}
mainFrame.getContentPane().add( simpleTabbedPane );
mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible( true );
}
public static void main(String[] args)
{
new JTabbedPaneDemo();
}
}
[/code]
21.JFormattedTextField
在講JFormattedTextField之前,先講用於指定格式的類:
Locale,NumberFormat,DecimalFormat,DecimalFormatSymbols,DateFormat,SimpleDateFormat,DateFormatSymbols
根據地區/語言(Locale)的不同,各種數字,日期的格式會有所不同.例如902333這個數字在德國會寫作902.333,而在美國寫作902,333
建立Locale可以使用它的構造方法,也可以使用它的一些常量.例如下面兩個語句是等價的:
Locale locale1 = new Locale("zh","CN");
Locale locale2 = Locale.CHINA;
上面用到的"zh"(小寫)和"CN"(大寫)分別遵循著一定的規定,在下面的連結可以找到這些搭配:
http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt
http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
你可以用任意的"xx"和"XX"搭配來建立Locale,但是,並不是所有都是有意義的,即Locale不一定可被上面的XXXFormat使用.
使用下面的程式可以得到DateFormat可以使用的組合:


[code]
package blog.swing;
import java.util.Locale;
import java.text.DateFormat;
class AvailableLocale
{
public static void main(String[] args)
{
Locale[] locales = DateFormat.getAvailableLocales();
for( Locale locale : locales ){
System.out.println( locale.toString());
//System.out.println( locale.getDisplayName() );
}
}
}
[/code]
如果你不設定Locale,XXXFormat將使用預設的Locale.這個預設的Locale是和你所用的系統有關的
用Locale.getDefault()可以得到預設的Locale
NumberFormat可以用於數字,貨幣和百分數的格式化(根據不同的Locale).對於數字,貨幣和百分數,分別呼叫靜態方法getNumberInstanc(Locale),
getCurrencyInstance(Locale),getPercentInstance(Locale)來取得例項,再用String format(double)來返回格式化後的字串.
DecimalFormat是NumberFormat的子類,它對格式提供了更多的控制.在構造它的時候可以指定數字顯示格式.它不可以直接指定Locale.要指定Locale的時候,可以把一個NumberFormat強制轉換為DecimalFormat,再呼叫applyPattern(String pattern)來指定數字格式.
同樣它用String format(double)來返回格式化後的字串.
可以用DecimalFormatSymbols來指定數字裡面的各個符號,例如小數點.在DecimalFormat的構造方法裡傳入DecimalFormatSymbols就可以了.DecimalFormatSymbols還可以指定Locale,所以用了DecimalFormatSymbols就不用將一個NumberFormat轉換為Decimalformat以指定Locale了


[code]
package blog.swing;
import java.util.Locale;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
class NumberFormatDemo{
public static void main( String[] args ){
double number = 96356.127;
double currency = 56832.523;
double percent = 0.72;
String out;
Locale locales[] = { Locale.CHINA,Locale.US,Locale.GERMANY };
NumberFormat formats = NumberFormat.getNumberInstance();
for( int i=0; i<3; i++){
formats = NumberFormat.getNumberInstance( locales[i] );
out = formats.format( number );
System.out.println( out+" "+locales[i].getDisplayName() );
formats = NumberFormat.getCurrencyInstance( locales[i] );
out = formats.format( currency );
System.out.println( out+" "+locales[i].getDisplayName() );
formats = NumberFormat.getPercentInstance( locales[i] );
out = formats.format( percent );
System.out.println( out+" "+locales[i].getDisplayName() );
}
DecimalFormat df = new DecimalFormat();
String pattern = "@#,###.##";
df.applyPattern( pattern );
out = df.format(number);
System.out.println( out );
pattern = "#@###.####";
df.applyPattern( pattern );
out = df.format(number);
System.out.println( out );
df = (DecimalFormat)formats;
df.applyPattern("#,###.##");
out = df.format(number);
System.out.println( out );
DecimalFormatSymbols dfss = new DecimalFormatSymbols(Locale.GERMANY);
dfss.setDecimalSeparator('^');
df.setDecimalFormatSymbols( dfss );
df.applyPattern("00,000.000");
out = df.format(number);
System.out.println( out );
}
}
[/code]
pattern的格式應滿足:
pattern := subpattern{;subpattern}
subpattern := {prefix}integer{.fraction}{suffix}
prefix := '\\u0000'..'\\uFFFD' - specialCharacters
suffix := '\\u0000'..'\\uFFFD' - specialCharacters
integer := '#'* '0'* '0'
fraction := '0'* '#'*
上面講的都是和數字有關的,下面講的是和日期和時間有關的
和日期,時間有關的格式用DateFormat,它的用法和NumberFormat差不多,也是呼叫靜態方法來取得例項,再呼叫String format(Date)來返回格式化後的字串
這些靜態方法有:
DateFormat getDateInstance(),DateFormat getDateInstance(int style),DateFormat getDateInstance(int style, Locale aLocale)
DateFormat getTimeInstance(),DateFormat getTimeInstance(int style),DateFormat getTimeInstance(int style, Locale aLocale)
DateFormat getDateTimeInstance(),DateFormat getDateTimeInstance(int style),DateFormat getDateTimeInstance(int style, Locale aLocale)
第一個引數指定顯示的風格,根據第二個引數的不同,這些風格也有所不同.可以取的值有:
DEFAULT,LONG,MEDIUM,SHORT,FULL,它們都是DateFormat的靜態常量.
對應於數字的DecimalFormat,在日期時間方面,有一個SimpleDateFormat
與DecimalFormat不同的是,SimpleDateFormat在構造的時個就可指定Locale了.
與數字的DeciamlFormatSymblos對應,在日期時間方面,有一個DateFormatSymbols.


[code]
package blog.swing;
import java.util.Locale;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.DateFormatSymbols;
class DateTimeFormatDemo
{
public static void main(String[] args)
{
Calendar calendar = new GregorianCalendar();
Date date = calendar.getTime();
Locale[] locales = { Locale.CHINA,Locale.US,Locale.GERMANY };
String[] patterns = { "yy-MM-dd","E yyyy/MM/dd","yy.MM.dd.hh.mm.ss" };
DateFormat formats;
SimpleDateFormat sdf;
String out;
for( int i=0; i<3; i++ ){
formats = DateFormat.getDateInstance(DateFormat.DEFAULT,locales[i]);
out = formats.format( date );
System.out.println( out );
formats = DateFormat.getTimeInstance(DateFormat.LONG,locales[i]);
out = formats.format( date );
System.out.println( out );
formats = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,locales[i]);
out = formats.format( date );
System.out.println( out );
sdf = new SimpleDateFormat(patterns[i],locales[i]);
out = sdf.format( date );
System.out.println( out+" "+patterns[i] );
System.out.println( "=====================" );
}
DateFormatSymbols dfss = new DateFormatSymbols(Locale.CHINA);
sdf = new SimpleDateFormat();
String[] capitalDays = {
"","SUN-星期日", "MON-星期一", "TUE-星期二", "WED-星期三",
"THU-星期四", "FRI-星期五", "SAT-星期六"};
dfss.setShortWeekdays(capitalDays);
sdf.applyPattern("E");
sdf.setDateFormatSymbols( dfss );
out = sdf.format(date);
System.out.println( out );
}
}
[/code]

相關文章