论坛首页 Java企业应用论坛

swing组件介绍(2)

浏览 7597 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-08-20  
下面是一个JFormattedTextField的例子.在这个例子中的三个JFormattedTextField分别使用了NumberFormat的三个静态方法取得的NumberFormat,当它们失去焦点时,它们显示的文本就会被格式化再重新显示,如果输入的是无效的文本,则文本被重设为上次的有效文本.


package blog.swing;
import java.awt.GridLayout;
import java.awt.Container;
import javax.swing.BorderFactory;
import javax.swing.*;
import java.text.NumberFormat;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;

class JFormattedTextFieldDemo implements PropertyChangeListener
{
    JFrame mainFrame;
    JPanel mainPanel;
    JFormattedTextField priceFormattedTextField;
    JFormattedTextField discountFormattedTextField;
    JFormattedTextField paymentFormattedTextField;
    JLabel priceLabel;
    JLabel discountLabel;
    JLabel paymentLabel;
    NumberFormat priceFormat;
    NumberFormat discountFormat;
    NumberFormat paymentFormat;
    public JFormattedTextFieldDemo() {
        mainFrame = new JFrame ( "JFormattedTextFieldDemo" );
        mainPanel = new JPanel ( new GridLayout(3,2) );
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

        priceFormat = NumberFormat.getNumberInstance();
        priceFormattedTextField = new JFormattedTextField(priceFormat);
        priceFormattedTextField.setValue(72.023);
        priceFormattedTextField.addPropertyChangeListener("value",this);
        priceLabel = new JLabel ("Price");
        priceLabel.setLabelFor( priceFormattedTextField );
        mainPanel.add( priceLabel );
        mainPanel.add( priceFormattedTextField );

        discountFormat = NumberFormat.getPercentInstance();
        discountFormattedTextField = new JFormattedTextField(discountFormat);
        discountFormattedTextField.setValue(0.75);
        discountFormattedTextField.addPropertyChangeListener("value",this);
        discountLabel = new JLabel ("Discount");
        discountLabel.setLabelFor( discountFormattedTextField );
        mainPanel.add( discountLabel );
        mainPanel.add( discountFormattedTextField );

        paymentFormat = NumberFormat.getCurrencyInstance();
        paymentFormattedTextField = new JFormattedTextField(paymentFormat);
        paymentFormattedTextField.setEditable( false );
        paymentFormattedTextField.addPropertyChangeListener("value",this);
        paymentLabel = new JLabel ("Payment");
        paymentLabel.setLabelFor( paymentFormattedTextField );
        mainPanel.add( paymentLabel );
        mainPanel.add( paymentFormattedTextField );

        mainFrame.getContentPane().add( mainPanel );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    public void propertyChange( PropertyChangeEvent e ){
        double price = ((Number)priceFormattedTextField.getValue()).doubleValue();
        double discount = ((Number)discountFormattedTextField.getValue()).doubleValue();
        paymentFormattedTextField.setValue( price*discount );
    }
    public static void main(String[] args) 
    {
        new JFormattedTextFieldDemo();
    }
}

除了使用上面讲到的java.text包中的各种formatter,还可以使用javax.swing.text.MaskFormatter来限制用户可以输入的字符


package blog.swing;
import javax.swing.*;
import javax.swing.text.MaskFormatter;
import java.text.ParseException;
class  MaskFormatterDemo
{
    JFrame mainFrame;
    JFormattedTextField simpleFormattedTextField;
    MaskFormatter mask;
    public MaskFormatterDemo(){
        mainFrame = new JFrame ( "MaskFormatterDemo" );
        try{
            mask = new MaskFormatter("####");
            simpleFormattedTextField = new JFormattedTextField( mask );        
            mainFrame.getContentPane().add( simpleFormattedTextField );
        }catch( ParseException e ){
            e.printStackTrace();
        }
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    public static void main(String[] args) 
    {
        new MaskFormatterDemo();
    }
}

22.JSpinner
微调组件.
微调组件由Editor,微调按钮,和它的Model组成.
在构造JSpinner时,可以指定它的Model.
swing提供了三个Model:
SpinnerListModel,SpinnerNumberModel,SpinnerDateModel
结构是SpinnerModel
  |_AbstractSpinnerModel
   |_SpinnerListModel,SpinnerNumberModel,SpinnerDateModel
对应有三个Editor:
JSpinner.ListEditor,JSpinner.NumberEditor,JSpinner.DateEditor,三个都是JSpinner.DefaultEditor的子类
JSpinner.DefaultEditor
|_JSpinner.ListEditor,JSpinner.NumberEditor,JSpinner.DateEditor
可以看到,有很大的空间可以自定义一个JSpinner
当你需要自定义它的Editor时,你可以用void setEditor(JComponent editor),也可以用JSpinner.DefaultEditor.getTextField()来取得JFormattedTextField,然后对这个JFormattedTextField来调用方法.
可以通过addChangeListener对JSpinner值的改变作出反应.


package blog.swing;
import java.awt.GridLayout;
import java.awt.Color;
import javax.swing.*;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
import java.util.Date;
import java.util.Calendar;
import java.text.DecimalFormat;

class JSpinnerDemo implements ChangeListener
{
    JFrame mainFrame;
    JPanel mainPanel;
    JSpinner listSpinner;
    JSpinner numberSpinner;
    JSpinner dateSpinner;
    public JSpinnerDemo() {
        mainFrame = new JFrame ( "JSpinnerDemo" );
        mainPanel = new JPanel ( new GridLayout(3,1) );
        
        String[] listData = { "SpinnerListModel","SpinnerNumberModel","SpinnerDateModel" };
        //使用自定义的Model来实现cycle
        SpinnerModel listModel = new CustomSpinnerListModel(listData);
        listSpinner = new JSpinner( listModel );
        listSpinner.addChangeListener( this );
        mainPanel.add(listSpinner);

        SpinnerModel numberModel = new SpinnerNumberModel(1.0,0.0,2.0,0.1);
        numberSpinner = new JSpinner( numberModel );
        numberSpinner.addChangeListener( this );
        //通过取得JFormattedTextField来自定义Editor
        JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor)numberSpinner.getEditor();
        JFormattedTextField ftf = editor.getTextField();
        ftf.setForeground( Color.red );
        mainPanel.add( numberSpinner );

        Calendar calendar = Calendar.getInstance();
        Date initDate = calendar.getTime();
        calendar.add(Calendar.YEAR,-100);
        Date earliestDate = calendar.getTime();
        calendar.add(Calendar.YEAR,200);
        Date latestDate = calendar.getTime();
        SpinnerModel dateModel = new SpinnerDateModel(initDate,earliestDate,latestDate,Calendar.YEAR);
        dateSpinner = new JSpinner( dateModel );
        dateSpinner.addChangeListener( this );
        //通过setEditor来自定义Editor
        dateSpinner.setEditor( new JSpinner.DateEditor(dateSpinner,"yyyy-MM-dd") );
        mainPanel.add(dateSpinner);

        mainPanel.setBorder( BorderFactory.createEmptyBorder(10,10,10,10) );
        mainFrame.getContentPane().add( mainPanel );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    public void stateChanged( ChangeEvent e ){
        JSpinner spinner = (JSpinner)e.getSource();
        System.out.println( spinner.getValue() );
    }
    //自定义的Model,实现Cycle.
    class CustomSpinnerListModel extends SpinnerListModel{
        Object[] values;
        CustomSpinnerListModel( Object[] values ){
            super(values);
            this.values = values;
        }
        public Object getPreviousValue(){
            Object value = super.getPreviousValue();
            return value != null ? value : values[values.length-1];
        }
        public Object getNextValue(){
            Object value = super.getNextValue();
            return value != null ? value : values[0];
        }
    }
    public static void main(String[] args) 
    {
        new JSpinnerDemo();
    }
}

23.JTree
这个组件太复杂了,只能很简单很简单地介绍一下.
一树由根节点和子节点组成.它们都是由DefaultMutableTreeNode表示
根节点是必须的,子节点可有可无.
传给DefaultMutableTreeNode的构造方法的是一个Object.在构造JTree的时候,会调用这个Object的toString()取得显示在JTree上的节点的文本.
调用void add(MutableTreeNode newChild)来增加一个子节点.
在构造JTree时,将用DefaultMutableTreeNode表示的根传入构造方法JTree(TreeNode root) ,这样就可以构造一棵树.
JTree用TreeSelectionModel来维护它的选择项,默认使用的是它的实现类DefaultTreeSelectionModel.
通过它的void addTreeSelectionListener(TreeSelectionListener x)可以对选择作出反应.
自定义JTree的外观
void setRootVisible(boolean rootVisible) 可以设置是否隐藏根节点
void setShowsRootHandles(boolean newValue) 设置是否显示节点前面的加号
void putClientProperty(Object key,Object value)设置节点之间的连线的样式
要自定义节点的图标,可以使用DefaultTreeCellRenderer,它是JLabel的一个字类
void setClosedIcon(Icon icon)设置非展开时的图标
void setOpenIcon(Icon newIcon) 设置节点展开时的图标
void setLeafIcon(Icon newIcon) 设置叶节点的图标
它也有一般Renderer类有的方法:
Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus)
通过这个方法可以定义每个节点所显示的组件
JTree的void setEditable(boolean)可以设置是否可以就地编辑该树
通过JTree的数据Model TreeModel的void addTreeModelListener(TreeModelListener l),我们可以在发生编辑的时候作出反应.
简单的应用可以使用TreeModel的实现类DefaultTreeModel.它的构造和JTree一样,也是把树的根节点传进去,DefaultTreeModel(TreeNode root).
创建了它以后,就可以用JTree的另外一个构造方法JTree(TreeModel newModel)来构造一棵树.


package blog.swing;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.tree.*;
class JTreeDemo 
{
    JFrame mainFrame;
    JScrollPane scrollPane;
    JTree simpleTree;
    JButton addButton;
    JButton removeButton;
    JTextField insertField;
    JPanel panel;
    public JTreeDemo() {
        mainFrame = new JFrame ( "JTreeDemo" );
        DefaultMutableTreeNode swing = new DefaultMutableTreeNode("Swing");
        buildTree(swing);
        simpleTree = new JTree(swing);
        simpleTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener(){
            public void valueChanged( TreeSelectionEvent e ){
                System.out.println( "selection changed" );
            }
        });
        simpleTree.setRootVisible(false);
        simpleTree.setShowsRootHandles(false);
        simpleTree.putClientProperty("JTree.lineStyle","Horizontal");
        simpleTree.putClientProperty("JTree.lineStyle","None");
        simpleTree.setCellRenderer( new CustomTreeCellRenderer() );
        simpleTree.setEditable( true );
        simpleTree.getModel().addTreeModelListener(new TreeModelListener(){
                public void treeNodesChanged(TreeModelEvent e) {
                    System.out.println("node changed");
                }
                public void treeNodesInserted(TreeModelEvent e) {
                    System.out.println( "node inserted" );
                }
                public void treeNodesRemoved(TreeModelEvent e) {
                    System.out.println("node removed");
                }
                public void treeStructureChanged(TreeModelEvent e) {
                    System.out.println( "strutrued changed" );
                }
            });
        scrollPane = new JScrollPane( simpleTree );

        addButton = new JButton ("add");
        addButton.addActionListener( new ActionListener(){
            public void actionPerformed( ActionEvent e){
                TreePath parentPath = simpleTree.getSelectionPath();
                if( parentPath != null ){
                    DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode)parentPath.getLastPathComponent();
                    DefaultTreeModel model = (DefaultTreeModel)simpleTree.getModel();
                    DefaultMutableTreeNode child = new DefaultMutableTreeNode( insertField.getText() );
                    model.insertNodeInto( child , parentNode,0 );
                    simpleTree.scrollPathToVisible( new TreePath( child.getPath() ) ); 
                }
            }
        });
        removeButton = new JButton ("remove");
        removeButton.addActionListener( new ActionListener(){
            public void actionPerformed( ActionEvent e){
                TreePath path = simpleTree.getSelectionPath();
                if( path != null ){
                    DefaultMutableTreeNode removeNode = (DefaultMutableTreeNode)path.getLastPathComponent();
                    DefaultTreeModel model = (DefaultTreeModel)simpleTree.getModel();
                    model.removeNodeFromParent( removeNode );
                }
            }
        });
        insertField = new JTextField(20);
        panel = new JPanel ( new GridLayout(15,1) );
        panel.add(insertField);
        panel.add( addButton );
        panel.add( removeButton );

        mainFrame.getContentPane().add( panel,BorderLayout.LINE_START );
        mainFrame.getContentPane().add( scrollPane,BorderLayout.LINE_END  );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    private void buildTree(DefaultMutableTreeNode root){
        DefaultMutableTreeNode parent;
        DefaultMutableTreeNode child;
        parent = new DefaultMutableTreeNode("Containers");
        child = new DefaultMutableTreeNode("JFrame");
        parent.add(child);
        child = new DefaultMutableTreeNode("JPanel");
        parent.add(child);
        child = new DefaultMutableTreeNode("JDialog");
        parent.add(child);
        root.add(parent);
        parent = new DefaultMutableTreeNode("Components");
        child = new DefaultMutableTreeNode("JButton");
        parent.add(child);
        child = new DefaultMutableTreeNode("JLabel");
        parent.add(child);
        child = new DefaultMutableTreeNode("JList");
        parent.add(child);
        root.add(parent);
    }
    private class CustomTreeCellRenderer extends DefaultTreeCellRenderer{
        public CustomTreeCellRenderer(){
            /*setLeafIcon( new ImageIcon("images/leaf.gif") );
            setOpenIcon( new ImageIcon("images/expand.gif") );
            setClosedIcon( new ImageIcon("images/unexpand.gif") );*/
        }
        public Component getTreeCellRendererComponent(
            JTree tree, Object value,
            boolean sel, boolean expanded,
            boolean leaf, int row, boolean hasFocus){
            JButton button = new JButton ( value.toString() );
            if( leaf )
                button.setIcon(new ImageIcon("images/leaf.gif") );
            else{
                if( expanded )
                    button.setIcon(new ImageIcon("images/expand.gif") );
                else
                    button.setIcon(new ImageIcon("images/unexpand.gif") );
            }
            return button;
        }
    }
    public static void main(String[] args) 
    {
        new JTreeDemo();
    }
}
   

24.Jtable 表格组件
应网友要求,勉强加上JTable的用法讲述.写得不好,望不见怪

没有比这个组件更复杂的了
它由标题头和单元格组成.而单元格又分为编辑状态和非编辑状态.自定义JTable主要是对单元格作文章.默认的单元格是一个label,和JTree一样,如果你在创建JTable的时候传递的是其他对象而不是String对象,则该对象的toString方法将被调用.它返回的字符串就会显示在单元格的label里.同以往一样,可以通过”渲染器”将其他组件显示在单元格里;而编辑状态下的单元格默认是一个文本框.可以通过指定CellEditor来指定其他的组件作为编辑状态下单元格的组件(简称编辑器).你可以为某一种类型的数据指定一种编辑器,也可以为一整列的数据指定特定的编辑器.编辑器可以用作验证用户输入的合法性.对于渲染器和编辑器的概念,是和JTree里的相似的
这个组件一般放在一个滚动窗格里.你可以把一个表格作为滚动窗格的viewport,然后再把滚动窗格添加到主框架的内容窗格(content pane)里.如果你不这样做,那么你必须分别把表格头和表格添加到框架窗口的content pane里.
这个组件也是用所谓的模型来保存它的数据的.TableModel就是用来保存数据的.而它和JList一样,用ListSelectionModel来保存选择了的项.另外它还有TableColumnModel来保存关于列的数据.下面几幅图总结了各部Model和Renderer的父子关系.
下面是例子程序
/*本程序演示了如何自定义自己的渲染器,自已的编辑器,和自己的数据模型
其中渲染器使得数据是Color类型时显示一个带颜色的JLabel
当数据是Color类型时编辑器是一个按钮,用以选择颜色*/

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

class JTableTest 
{
    JFrame mainFrame;
    JPanel mainPanel;
    JTable table;
    JScrollPane scrollPane;
    public JTableTest() {

        mainFrame = new JFrame ( "JTableTest" );
        mainPanel = new JPanel ( new BorderLayout() );

        String[] columnName = { "Name","Age","Favorite Color","Career","Married" };
        Object[][] data = { { "kate", new Integer(34),new Color(255,0,0),"engineer", new Boolean(true) },
                             { "jim", new Integer(56),Color.white,"manager", new Boolean(false) },
                            { "roy", new Integer(23),Color.black,"driver", new Boolean(false) },
                            { "paul", new Integer(33),Color.blue,"teacher", new Boolean(true) }};

        CustomTableModel customModel = new CustomTableModel( data,columnName );//自定义的数据模型
        table = new JTable( customModel ){//在构造方法里传递数据模型作为参数
            public String getToolTipText( MouseEvent e){//设定工具提示
                int row = rowAtPoint( e.getPoint() );
                int column = columnAtPoint( e.getPoint() );
                int realColumn = convertColumnIndexToModel( column );
                if( realColumn == 3 ){
                    TableModel model = getModel();
                    String name = (String)model.getValueAt( row, 0 );
                    String career = (String)model.getValueAt( row, realColumn );
                    return name + "'s" + "career is " + career;
                }
                return null;
            }

            public TableCellEditor getCellEditor(int row, int column) {
                if ((row == 1) && (column == 2)) {
                    return new CustomCellEditor();//好像没起作用?
                }
                return super.getCellEditor(row, column);
            }
        };
        table.getTableHeader().setToolTipText("click here can't sort the contents");//设置标题头的工具提示.排序功能并未实现
        ListSelectionModel rowSm = table.getSelectionModel();
        rowSm.addListSelectionListener( new ListSelectionListener(){
            public void valueChanged( ListSelectionEvent e ){
                ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                System.out.println( lsm.getMaxSelectionIndex() );
            }
        } );

        TableColumn column = table.getColumnModel().getColumn(3);
        JComboBox combox = new JComboBox();
        combox.addItem("engineer");
        combox.addItem("students");
        combox.addItem("driver");
        combox.addItem("teacher");
        column.setCellEditor( new DefaultCellEditor( combox ) );//为一整列指定编辑器

        table.setDefaultEditor( Color.class , new CustomCellEditor() );//为特定的数据类型指定编辑器
        table.setDefaultRenderer( Color.class , new CustomRenderer() );


        TableModel tableModel = table.getModel();
        tableModel.addTableModelListener( new TableModelListener(){
            public void tableChanged( TableModelEvent e ){
                TableModel model = (TableModel)e.getSource();
                int row = e.getFirstRow();
                int column = e.getColumn();

                System.out.println( model.getValueAt( row, column ) );
                System.out.println( model.getColumnName( column ) );
            }
        } );

        mainPanel.add(table.getTableHeader(),BorderLayout.PAGE_START);
        mainPanel.add(table,BorderLayout.CENTER);
        scrollPane = new JScrollPane (mainPanel);//这样,表头会自动添加到滚动空格里;否则,则要使用下面三行将标题头也添加到框架窗口
/*        mainFrame.getContentPane().setLayout(new BorderLayout());
        mainFrame.getContentPane().add(table.getTableHeader(), BorderLayout.PAGE_START);
        mainFrame.getContentPane().add(table, BorderLayout.CENTER);*/


        mainFrame.getContentPane().add( scrollPane );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    private class CustomTableModel extends AbstractTableModel{//自定义的数据类型
        String[] columnName;
        Object[][] data;
        CustomTableModel(Object[][] data,String[] columnName){
            this.columnName = columnName;
            this.data = data;
        }
        public Object getValueAt( int rowIndex, int columnIndex ){
            return data[rowIndex][columnIndex];
        }
        public int getColumnCount(){
            return data[0].length;
        }
        public int getRowCount(){
            return data.length;
        }
        public String getColumnName( int columnIndex ){
            return columnName[columnIndex];
        }
        public Class getColumnClass( int columnIndex ){
            return getValueAt(0,columnIndex).getClass();

        }
        public void setValueAt( Object value, int row, int column ){
            data[row][column] = value;
            fireTableCellUpdated(row,column);
        }
        public boolean isCellEditable(int row ,int column){
            return true;
        }
    }
    //自定义的编辑器
    private class CustomCellEditor extends AbstractCellEditor implements TableCellEditor,ActionListener{
        Color currentColor;
        JButton button;
        JColorChooser chooser;
        JDialog dialog;
        CustomCellEditor(){
            button = new JButton ();
            button.addActionListener( this );
            button.setActionCommand("editor");
            chooser = new JColorChooser();
            dialog = JColorChooser.createDialog( button,"pick a color",true,chooser,this,null);
        }
        public void actionPerformed( ActionEvent e ){
            if( e.getActionCommand().equals( "editor" ) ){
                button.setBackground( currentColor );
                chooser.setColor(currentColor);
                dialog.setVisible( true );
                fireEditingStopped();
            }else{                
                
                currentColor = chooser.getColor();
            }
        }
        public Object getCellEditorValue(){
            return currentColor;
        }
        public Component getTableCellEditorComponent( JTable table,Object value,boolean isSelected,int row,int column){
            currentColor = (Color)value;
            return button;
        }
    }
    //自定义的渲染器
    private class CustomRenderer extends JLabel implements TableCellRenderer{
        CustomRenderer(){
            setOpaque(true);
        }
        public Component getTableCellRendererComponent(
            JTable table,Object value,boolean isSelected,
            boolean hasFocus,int row,int column){
                setBackground( (Color)value );
                setToolTipText( "RGB Value: "+((Color)value).getRed()+" "
                    +((Color)value).getGreen()+" "+((Color)value).getBlue() );
                return this;
        }
        
    }
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater( new Runnable(){
            public void run(){
                new JTableTest();
            }
        });
    }
}

  

24.Jtable 表格组件
没有比这个组件更复杂的了
它由标题头和单元格组成.而单元格又分为编辑状态和非编辑状态.自定义JTable主要是对单元格作文章.默认的单元格是一个label,和JTree一样,如果你在创建JTable的时候传递的是其他对象而不是String对象,则该对象的toString方法将被调用.它返回的字符串就会显示在单元格的label里.同以往一样,可以通过”渲染器”将其他组件显示在单元格里;而编辑状态下的单元格默认是一个文本框.可以通过指定CellEditor来指定其他的组件作为编辑状态下单元格的组件(简称编辑器).你可以为某一种类型的数据指定一种编辑器,也可以为一整列的数据指定特定的编辑器.编辑器可以用作验证用户输入的合法性.对于渲染器和编辑器的概念,是和JTree里的相似的
这个组件一般放在一个滚动窗格里.你可以把一个表格作为滚动窗格的viewport,然后再把滚动窗格添加到主框架的内容窗格(content pane)里.如果你不这样做,那么你必须分别把表格头和表格添加到框架窗口的content pane里.
这个组件也是用所谓的模型来保存它的数据的.TableModel就是用来保存数据的.而它和JList一样,用ListSelectionModel来保存选择了的项.另外它还有TableColumnModel来保存关于列的数据.下面几幅图总结了各部Model和Renderer的父子关系.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.event.*;
import javax.swing.table.*;

class JTableTest 
{
    JFrame mainFrame;
    JPanel mainPanel;
    JTable table;
    JScrollPane scrollPane;
    public JTableTest() {

        mainFrame = new JFrame ( "JTableTest" );
        mainPanel = new JPanel ( new BorderLayout() );

        String[] columnName = { "Name","Age","Favorite Color","Career","Married" };
        Object[][] data = { { "kate", new Integer(34),new Color(255,0,0),"engineer", new Boolean(true) },
                             { "jim", new Integer(56),Color.white,"manager", new Boolean(false) },
                            { "roy", new Integer(23),Color.black,"driver", new Boolean(false) },
                            { "paul", new Integer(33),Color.blue,"teacher", new Boolean(true) }};

        CustomTableModel customModel = new CustomTableModel( data,columnName );//自定义的数据模型
        table = new JTable( customModel ){//在构造方法里传递数据模型作为参数
            public String getToolTipText( MouseEvent e){//设定工具提示
                int row = rowAtPoint( e.getPoint() );
                int column = columnAtPoint( e.getPoint() );
                int realColumn = convertColumnIndexToModel( column );
                if( realColumn == 3 ){
                    TableModel model = getModel();
                    String name = (String)model.getValueAt( row, 0 );
                    String career = (String)model.getValueAt( row, realColumn );
                    return name + "'s" + "career is " + career;
                }
                return null;
            }

            public TableCellEditor getCellEditor(int row, int column) {
                if ((row == 1) && (column == 2)) {
                    return new CustomCellEditor();//好像没起作用?
                }
                return super.getCellEditor(row, column);
            }
        };
        table.getTableHeader().setToolTipText("click here can't sort the contents");//设置标题头的工具提示.排序功能并未实现
        ListSelectionModel rowSm = table.getSelectionModel();
        rowSm.addListSelectionListener( new ListSelectionListener(){
            public void valueChanged( ListSelectionEvent e ){
                ListSelectionModel lsm = (ListSelectionModel)e.getSource();
                System.out.println( lsm.getMaxSelectionIndex() );
            }
        } );

        TableColumn column = table.getColumnModel().getColumn(3);
        JComboBox combox = new JComboBox();
        combox.addItem("engineer");
        combox.addItem("students");
        combox.addItem("driver");
        combox.addItem("teacher");
        column.setCellEditor( new DefaultCellEditor( combox ) );//为一整列指定编辑器

        table.setDefaultEditor( Color.class , new CustomCellEditor() );//为特定的数据类型指定编辑器
        table.setDefaultRenderer( Color.class , new CustomRenderer() );


        TableModel tableModel = table.getModel();
        tableModel.addTableModelListener( new TableModelListener(){
            public void tableChanged( TableModelEvent e ){
                TableModel model = (TableModel)e.getSource();
                int row = e.getFirstRow();
                int column = e.getColumn();

                System.out.println( model.getValueAt( row, column ) );
                System.out.println( model.getColumnName( column ) );
            }
        } );

        mainPanel.add(table.getTableHeader(),BorderLayout.PAGE_START);
        mainPanel.add(table,BorderLayout.CENTER);
        scrollPane = new JScrollPane (mainPanel);//这样,表头会自动添加到滚动空格里;否则,则要使用下面三行将标题头也添加到框架窗口
/*        mainFrame.getContentPane().setLayout(new BorderLayout());
        mainFrame.getContentPane().add(table.getTableHeader(), BorderLayout.PAGE_START);
        mainFrame.getContentPane().add(table, BorderLayout.CENTER);*/


        mainFrame.getContentPane().add( scrollPane );
        mainFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible( true );
    }
    private class CustomTableModel extends AbstractTableModel{//自定义的数据类型
        String[] columnName;
        Object[][] data;
        CustomTableModel(Object[][] data,String[] columnName){
            this.columnName = columnName;
            this.data = data;
        }
        public Object getValueAt( int rowIndex, int columnIndex ){
            return data[rowIndex][columnIndex];
        }
        public int getColumnCount(){
            return data[0].length;
        }
        public int getRowCount(){
            return data.length;
        }
        public String getColumnName( int columnIndex ){
            return columnName[columnIndex];
        }
        public Class getColumnClass( int columnIndex ){
            return getValueAt(0,columnIndex).getClass();

        }
        public void setValueAt( Object value, int row, int column ){
            data[row][column] = value;
            fireTableCellUpdated(row,column);
        }
        public boolean isCellEditable(int row ,int column){
            return true;
        }
    }
    //自定义的编辑器
    private class CustomCellEditor extends AbstractCellEditor implements TableCellEditor,ActionListener{
        Color currentColor;
        JButton button;
        JColorChooser chooser;
        JDialog dialog;
        CustomCellEditor(){
            button = new JButton ();
            button.addActionListener( this );
            button.setActionCommand("editor");
            chooser = new JColorChooser();
            dialog = JColorChooser.createDialog( button,"pick a color",true,chooser,this,null);
        }
        public void actionPerformed( ActionEvent e ){
            if( e.getActionCommand().equals( "editor" ) ){
                button.setBackground( currentColor );
                chooser.setColor(currentColor);
                dialog.setVisible( true );
                fireEditingStopped();
            }else{                
                
                currentColor = chooser.getColor();
            }
        }
        public Object getCellEditorValue(){
            return currentColor;
        }
        public Component getTableCellEditorComponent( JTable table,Object value,boolean isSelected,int row,int column){
            currentColor = (Color)value;
            return button;
        }
    }
    //自定义的渲染器
    private class CustomRenderer extends JLabel implements TableCellRenderer{
        CustomRenderer(){
            setOpaque(true);
        }
        public Component getTableCellRendererComponent(
            JTable table,Object value,boolean isSelected,
            boolean hasFocus,int row,int column){
                setBackground( (Color)value );
                setToolTipText( "RGB Value: "+((Color)value).getRed()+" "
                    +((Color)value).getGreen()+" "+((Color)value).getBlue() );
                return this;
        }
        
    }
    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater( new Runnable(){
            public void run(){
                new JTableTest();
            }
        });
    }
}
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics