`
dzgwt2004
  • 浏览: 164784 次
  • 来自: 浙江杭州
社区版块
存档分类
最新评论

swing组件介绍(1)

    博客分类:
  • java
阅读更多
学习swing组件,主要有三个内容
一是组件的显示,二是对组件支持的事件进行侦听,三是是自定义组件
1.JFrame
JFrame是主窗口,它和JDialog,JApplet的地位并列.但是,一个JFrame可以添加JDialog和JApplet进去它的内容面板,而反过来就不行
下面来看JFrame的例子
=================================================

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();
 }
}


==========================================================
这里出现了三个不同的窗口事件侦听器,并实现了它们所有的方法
WindowListener和WindowFocusListener都可以对窗口失去,获得焦点进行侦听,不同的是,非帧窗口和对话框窗口不能接收WindowListener的windowActivated和windodwDeactivated事件
虽然可以用WindowListener对窗口的一些状态进行侦听,但是WindowStateListener提供了更多的支持.例如,WindowStateListener可以处理还原窗口的事件,可以判断一个窗口是不是在垂直和水平两个方向都可以最大化(命令提示符窗口只可以在垂直方向上最大化),而这些都是WindowListener都无能为力
2.JLabel
JLabel是一标签.在它的文本里嵌入html标签,可以简单实现一个超链接组件


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();
 }
}

3.JButton
JButton是一个按钮.它和JLabel一样的简单


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();
 }
}


4.JTextField
一个文本框


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();
 }
}


5.JTextArea
文本区域,与文本框不同的是它是多行的


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();
 }
}


6.JPasswordField

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();
 }
}


7.JPanel
一个面板.一般用作控制组件的布局.

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();
 }
}


8.JCheckBox
复选框

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();
 }
}


9.JRadioButton
单选按钮.单选按钮要用到ButtonGroup.添加到同一个ButtonGroup的单选按钮表示在它们之间只可选其一.不同ButtonGroup里的单选按钮相互之间的选择不受影响.

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();
 }
}


10.JScrollPane
JScrollPane由四个角,两个头部,和一个视口组成.四个角和两个头部都是由Component组成.四个角并不是总是显示出来的.左上角只有当两个头部同时存在才显示,右下角只有两个滚动条同时出现才会出现.其他两个角可同理知道什么时候会出现.视口是显示内容的部分,由JViewport对象表示.而真正显示的内容,由JViewport的view表示

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();
 }
}


现在开始讲相对复杂一点的组件
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了.

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 );
 }
 
}


 

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();
 }
}


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里显示图片

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;
        }
    }
}

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)


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();
    }
}

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() 负责更新显示颜色面板


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();
    }
}
 

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();
    }
} 

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()


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();
    }
}

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是指在层内的位置.


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();
    }
}

17.JInternalFrame
JFrame不能添加JFrame到自已的内容面板.那么,如何实现多文档程序呢?用JInternalFrame可以实现.
一般的做法是,把JInternalFrame添加到JDesktopPane,然后把JDesktopPane作为JFrame的内容面板(ContentPane)
JInternalFrame(String title[, boolean resizable[, boolean closable[, boolean maximizable[, boolean iconifiable]]]])
[]里面的表示可以省略


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();
    }
}

18.GlassPane
GlassPane可以用来截获输入事件(键盘和鼠标).没有JGlassPane
可以调用JFrame的void setGlassPane(Component glassPane)来设置GlassPane
默认GlassPane是不可见的,要调用getGlassPane().setVisible(true)使其可见


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();
            }
        });
    }
}

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不再输出了,而是等到最后连续输出数个值.


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();
    }
}

除了用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():判断任务是否已被取消
下面是一个例子.


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);
        }
    }
}

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);


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();
    }
}

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可以使用的组合:


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() );
        }
    }
}

如果你不设定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了


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 );
    }
}

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.


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 );
    }
}


分享到:
评论
8 楼 niceo 2008-08-13  
呵呵!!
吧swing解说的这样。很好很好!!!
我在进行 AWT+ Swing +Java3D 做3D 的时候主要还是那Swing 来控制全局的。
7 楼 lesskao 2008-08-13  
<div class='quote_title'>sai2726 写道</div>
<div class='quote_div'>
<div class='quote_title'>jvincent 写道</div>
<div class='quote_div'>B/S的企业应用通过Applet加载Swing,可以实现较好的操作体验,有些是Web界面无法实现的...</div>
good</div>
<p>   如果有条件建议看下用友的NC ERP,就是通过你说的方式来实现的。</p>
<p> </p>
6 楼 wareis 2007-09-20  
顶,支持多写些Swing的文章
5 楼 jvincent 2007-09-19  
其实就是在Applet中使用Swing包的组件,客户端需要现在一个jre,由于Applet默认不能访问本地资源,需要签名来放开权限。
4 楼 myreligion 2007-09-14  
Applet加载swing?好像是个不错的思路,愿闻其祥,有没有参考的例子或者资料推荐下?
3 楼 sai2726 2007-09-14  
jvincent 写道
B/S的企业应用通过Applet加载Swing,可以实现较好的操作体验,有些是Web界面无法实现的...
good
2 楼 jvincent 2007-08-21  
B/S的企业应用通过Applet加载Swing,可以实现较好的操作体验,有些是Web界面无法实现的...
1 楼 lgx522 2007-08-21  
Swing是非常棒的东西!MVC发挥得淋漓尽致,组件重用度极高。
最近在搞Spring RMI + Swing,其实是非常好的组合,强烈推荐在企业内部使用。

过些天有空发个入门帖。

相关推荐

Global site tag (gtag.js) - Google Analytics