Java Swing编程:JTable表格


表格是GUI编程中使用较多,但也是最麻烦的一个控件之一。表格是用来显示二维数据,提供编辑,选择等功能。如果只是显示数据,这还是非常easy的,只要在JTable中传入二维数组或集合就可以了。

表格是GUI编程中使用较多,但也是最麻烦的一个控件之一。表格是用来显示二维数据,提供编辑,选择等功能。如果只是显示数据,这还是非常easy的,只要在JTable中传入二维数组或集合就可以了,eg


  1. public class SimpleTable  
  2. {  
  3.     JFrame jf = new JFrame("简单表格");  
  4.     JTable table;  
  5.     //定义二维数组作为表格数据  
  6.     Object[][] tableData =   
  7.     {  
  8.         new Object[]{"李清照" , 29 , "女"},  
  9.         new Object[]{"苏格拉底"56 , "男"},  
  10.         new Object[]{"李白"35 , "男"},  
  11.         new Object[]{"弄玉"18 , "女"},  
  12.         new Object[]{"虎头" , 2 , "男"}  
  13.     };  
  14.     //定义一维数据作为列标题  
  15.     Object[] columnTitle = {"姓名" , "年龄" , "性别"};  
  16.     public void init()  
  17.     {  
  18.         //以二维数组和一维数组来创建一个JTable对象  
  19.         table = new JTable(tableData , columnTitle);  
  20.         //将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来  
  21.         jf.add(new JScrollPane(table));  
  22.         jf.pack();  
  23.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  24.         jf.setVisible(true);  
  25.     }  
  26.     public static void main(String[] args)   
  27.     {  
  28.         new SimpleTable().init();  
  29.     }  
  30. }  

下面举个JTable表格调整和选择方式的例子,eg


  1. public class AdjustingWidth  
  2. {  
  3.     JFrame jf = new JFrame("调整表格列宽");  
  4.     JMenuBar menuBar = new JMenuBar();  
  5.     JMenu adjustModeMenu = new JMenu("调整方式");  
  6.     JMenu selectUnitMenu = new JMenu("选择单元");  
  7.     JMenu selectModeMenu = new JMenu("选择方式");  
  8.  
  9.     //定义5个单选框按钮,用以控制表格的宽度调整方式  
  10.     JRadioButtonMenuItem[] adjustModesItem = new JRadioButtonMenuItem[5];  
  11.     //定义3个单选框按钮,用以控制表格的选择方式  
  12.     JRadioButtonMenuItem[] selectModesItem = new JRadioButtonMenuItem[3];  
  13.  
  14.     JCheckBoxMenuItem rowsItem = new JCheckBoxMenuItem("选择行");  
  15.     JCheckBoxMenuItem columnsItem = new JCheckBoxMenuItem("选择列");  
  16.     JCheckBoxMenuItem cellsItem = new JCheckBoxMenuItem("选择单元格");  
  17.     ButtonGroup adjustBg = new ButtonGroup();  
  18.     ButtonGroup selectBg = new ButtonGroup();  
  19.     //定义一个int类型的数组,用于保存表格所有的宽度调整方式  
  20.     int[] adjustModes = new int[]{  
  21.         JTable.AUTO_RESIZE_OFF,  
  22.         JTable.AUTO_RESIZE_NEXT_COLUMN,  
  23.         JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS,  
  24.         JTable.AUTO_RESIZE_LAST_COLUMN,  
  25.         JTable.AUTO_RESIZE_ALL_COLUMNS   
  26.     };  
  27.     int[] selectModes = new int[]{  
  28.         ListSelectionModel.MULTIPLE_INTERVAL_SELECTION ,  
  29.         ListSelectionModel.SINGLE_INTERVAL_SELECTION ,  
  30.         ListSelectionModel.SINGLE_SELECTION  
  31.     };  
  32.     JTable table;  
  33.     //定义二维数组作为表格数据  
  34.     Object[][] tableData =   
  35.     {  
  36.         new Object[]{"李清照" , 29 , "女"},  
  37.         new Object[]{"苏格拉底"56 , "男"},  
  38.         new Object[]{"李白"35 , "男"},  
  39.         new Object[]{"弄玉"18 , "女"},  
  40.         new Object[]{"虎头" , 2 , "男"}  
  41.     };  
  42.     //定义一维数据作为列标题  
  43.     Object[] columnTitle = {"姓名" , "年龄" , "性别"};  
  44.  
  45.     public void init()  
  46.     {  
  47.         //以二维数组和一维数组来创建一个JTable对象  
  48.         table = new JTable(tableData , columnTitle);  
  49.  
  50.         //-----------为窗口安装设置表格调整方式的菜单-----------  
  51.         adjustModesItem[0] = new JRadioButtonMenuItem("只调整表格");  
  52.         adjustModesItem[1] = new JRadioButtonMenuItem("只调整下一列");  
  53.         adjustModesItem[2] = new JRadioButtonMenuItem("平均调整余下列");  
  54.         adjustModesItem[3] = new JRadioButtonMenuItem("只调整最后一列");  
  55.         adjustModesItem[4] = new JRadioButtonMenuItem("平均调整所有列");  
  56.         menuBar.add(adjustModeMenu);  
  57.         for (int i = 0; i < adjustModesItem.length ; i++)  
  58.         {  
  59.             //默认选中第三个菜单项,即对应表格默认的宽度调整方式  
  60.             if (i == 2)  
  61.             {  
  62.                 adjustModesItem[i].setSelected(true);  
  63.             }  
  64.             adjustBg.add(adjustModesItem[i]);  
  65.             adjustModeMenu.add(adjustModesItem[i]);  
  66.             final int index = i;  
  67.             //为设置调整方式的菜单项添加监听器  
  68.             adjustModesItem[i].addActionListener(new ActionListener()  
  69.             {  
  70.                 public void actionPerformed(ActionEvent evt)  
  71.                 {  
  72.                     //如果当前菜单项处于选中状态,表格使用对应的调整方式  
  73.                     if (adjustModesItem[index].isSelected())  
  74.                     {  
  75.                         table.setAutoResizeMode(adjustModes[index]);  
  76.                     }  
  77.                 }  
  78.             });  
  79.         }  
  80.         //-----------为窗口安装设置表格选择方式的菜单-----------  
  81.         selectModesItem[0] = new JRadioButtonMenuItem("无限制");  
  82.         selectModesItem[1] = new JRadioButtonMenuItem("单独的连续区");  
  83.         selectModesItem[2] = new JRadioButtonMenuItem("单选");  
  84.         menuBar.add(selectModeMenu);  
  85.         for (int i = 0; i < selectModesItem.length ; i++)  
  86.         {  
  87.             //默认选中第一个菜单项,即对应表格默认的选择方式  
  88.             if (i == 0)  
  89.             {  
  90.                 selectModesItem[i].setSelected(true);  
  91.             }  
  92.             selectBg.add(selectModesItem[i]);  
  93.             selectModeMenu.add(selectModesItem[i]);  
  94.             final int index = i;  
  95.             //为设置选择方式的菜单项添加监听器  
  96.             selectModesItem[i].addActionListener(new ActionListener()  
  97.             {  
  98.                 public void actionPerformed(ActionEvent evt)  
  99.                 {  
  100.                     //如果当前菜单项处于选中状态,表格使用对应的选择方式  
  101.                     if (selectModesItem[index].isSelected())  
  102.                     {  
  103.                         table.getSelectionModel().setSelectionMode(selectModes[index]);  
  104.                     }  
  105.                 }  
  106.             });  
  107.         }  
  108.         menuBar.add(selectUnitMenu);  
  109.         //-----------为窗口安装设置表格选择单元的菜单-----------  
  110.         rowsItem.setSelected(table.getRowSelectionAllowed());  
  111.         columnsItem.setSelected(table.getColumnSelectionAllowed());  
  112.         cellsItem.setSelected(table.getCellSelectionEnabled());  
  113.  
  114.         rowsItem.addActionListener(new ActionListener()  
  115.         {  
  116.             public void actionPerformed(ActionEvent event)  
  117.             {  
  118.                 table.clearSelection();  
  119.                 //如果该菜单项处于选中状态,设置表格的选择单元是行  
  120.                 table.setRowSelectionAllowed(rowsItem.isSelected());  
  121.                 //如果选择行、选择列同时被选中,其实质是选择单元格  
  122.                 cellsItem.setSelected(table.getCellSelectionEnabled());  
  123.             }  
  124.         });  
  125.         selectUnitMenu.add(rowsItem);  
  126.         columnsItem.addActionListener(new ActionListener()  
  127.         {  
  128.             public void actionPerformed(ActionEvent event)  
  129.             {  
  130.                 table.clearSelection();  
  131.                 //如果该菜单项处于选中状态,设置表格的选择单元是列  
  132.                 table.setColumnSelectionAllowed(columnsItem.isSelected());  
  133.                 //如果选择行、选择列同时被选中,其实质是选择单元格  
  134.                 cellsItem.setSelected(table.getCellSelectionEnabled());  
  135.             }  
  136.         });  
  137.         selectUnitMenu.add(columnsItem);  
  138.         cellsItem.addActionListener(new ActionListener()  
  139.         {  
  140.             public void actionPerformed(ActionEvent event)  
  141.             {  
  142.                 table.clearSelection();  
  143.                 //如果该菜单项处于选中状态,设置表格的选择单元是单元格  
  144.                 table.setCellSelectionEnabled(cellsItem.isSelected());  
  145.                 //该选项的改变会同时影响选择行、选择列两个菜单  
  146.                 rowsItem.setSelected(table.getRowSelectionAllowed());  
  147.                 columnsItem.setSelected(table.getColumnSelectionAllowed());  
  148.             }  
  149.         });  
  150.         selectUnitMenu.add(cellsItem);  
  151.  
  152.         jf.setJMenuBar(menuBar);  
  153.         //分别获取表格的三个表格列,并设置三列的最小宽度,最佳宽度和最大宽度  
  154.         TableColumn nameColumn = table.getColumn(columnTitle[0]);  
  155.         nameColumn.setMinWidth(40);  
  156.         TableColumn ageColumn = table.getColumn(columnTitle[1]);  
  157.         ageColumn.setPreferredWidth(50);  
  158.         TableColumn genderColumn = table.getColumn(columnTitle[2]);  
  159.         genderColumn.setMaxWidth(50);  
  160.  
  161.  
  162.         //将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来  
  163.         jf.add(new JScrollPane(table));  
  164.         System.out.println(table.getModel());  
  165.         jf.pack();  
  166.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  167.         jf.setVisible(true);  
  168.     }  
  169.  
  170.     public static void main(String[] args)   
  171.     {  
  172.         new AdjustingWidth().init();  
  173.     }  
  174. }  

和JList,JTree类似,JTable采用TableModel来保存表格中的所有状态数据,采用TableColumnModel来保存所有列的数据。eg


  1. public class TestDefaultTableModel  
  2. {  
  3.     JFrame mainWin = new JFrame("管理数据行、数据列");  
  4.     final int COLUMN_COUNT = 5;  
  5.     DefaultTableModel model;  
  6.     JTable table;  
  7.     //用于保存被隐藏列的List集合  
  8.     ArrayList<TableColumn> hiddenColumns = new ArrayList<TableColumn>();  
  9.     public void init()  
  10.     {  
  11.         model = new DefaultTableModel(COLUMN_COUNT ,COLUMN_COUNT);  
  12.         for (int i = 0; i < COLUMN_COUNT ; i++ )  
  13.         {  
  14.             for (int j = 0; j < COLUMN_COUNT ; j++ )  
  15.             {  
  16.                 model.setValueAt("老单元格值 " + i + " " + j , i , j);  
  17.             }  
  18.         }  
  19.  
  20.         table = new JTable(model);  
  21.  
  22.         mainWin.add(new JScrollPane(table), BorderLayout.CENTER);  
  23.  
  24.         //为窗口安装菜单  
  25.         JMenuBar menuBar = new JMenuBar();  
  26.         mainWin.setJMenuBar(menuBar);  
  27.         JMenu tableMenu = new JMenu("管理");  
  28.         menuBar.add(tableMenu);  
  29.  
  30.         JMenuItem hideColumnsItem = new JMenuItem("隐藏选中列");  
  31.         hideColumnsItem.addActionListener(new ActionListener()  
  32.         {  
  33.             public void actionPerformed(ActionEvent event)  
  34.             {  
  35.                 //获取所有选中列的索引  
  36.                 int[] selected = table.getSelectedColumns();  
  37.                 TableColumnModel columnModel = table.getColumnModel();  
  38.                 //依次把每一个选中的列隐藏起来,并使用List把这些列保存起来  
  39.                 for (int i = selected.length - 1; i >= 0; i--)  
  40.                 {  
  41.                     TableColumn column = columnModel.getColumn(selected[i]);  
  42.                     table.removeColumn(column);  
  43.                     //把隐藏的列保存起来,确保以后可以显示出来  
  44.                     hiddenColumns.add(column);  
  45.                 }  
  46.             }  
  47.         });  
  48.         tableMenu.add(hideColumnsItem);  
  49.  
  50.         JMenuItem showColumnsItem = new JMenuItem("显示隐藏列");  
  51.         showColumnsItem.addActionListener(new ActionListener()  
  52.         {  
  53.             public void actionPerformed(ActionEvent event)  
  54.             {  
  55.                 //把所有隐藏列依次显示出来  
  56.                 for (TableColumn tc : hiddenColumns)  
  57.                 {  
  58.                     //依次把所有隐藏的列显示出来  
  59.                     table.addColumn(tc);  
  60.                 }  
  61.                 //清空保存隐藏列的List集合  
  62.                 hiddenColumns.clear();              
  63.             }  
  64.         });  
  65.         tableMenu.add(showColumnsItem);  
  66.  
  67.         JMenuItem addColumnItem = new JMenuItem("插入选中列");  
  68.         addColumnItem.addActionListener(new ActionListener()  
  69.         {  
  70.             public void actionPerformed(ActionEvent event)  
  71.             {  
  72.                 //获取所有选中列的索引  
  73.                 int[] selected = table.getSelectedColumns();  
  74.                 TableColumnModel columnModel = table.getColumnModel();  
  75.                 //依次把选中的列添加到JTable之后  
  76.                 for (int i = selected.length - 1; i >= 0; i--)  
  77.                 {    
  78.                     TableColumn column = columnModel.getColumn(selected[i]);  
  79.                     table.addColumn(column);  
  80.                 }  
  81.             }  
  82.         });  
  83.         tableMenu.add(addColumnItem);  
  84.  
  85.         JMenuItem addRowItem = new JMenuItem("增加行");  
  86.         addRowItem.addActionListener(new ActionListener()  
  87.         {  
  88.             public void actionPerformed(ActionEvent event)  
  89.             {  
  90.                 //创建一个String数组作为新增行的内容  
  91.                 String[] newCells = new String[COLUMN_COUNT];  
  92.                 for (int i = 0; i < newCells.length; i++)  
  93.                 {  
  94.                     newCells[i] = "新单元格值 " + model.getRowCount() + " " + i;  
  95.                 }  
  96.                 //向TableModel中新增一行。  
  97.                 model.addRow(newCells);  
  98.             }  
  99.         });  
  100.         tableMenu.add(addRowItem);  
  101.  
  102.         JMenuItem removeRowsItem = new  JMenuItem("删除选中行");  
  103.         removeRowsItem.addActionListener(new ActionListener()  
  104.         {  
  105.             public void actionPerformed(ActionEvent event)  
  106.             {  
  107.                 //获取所有选中行  
  108.                 int[] selected = table.getSelectedRows();  
  109.                 //依次删除所有选中行  
  110.                 for (int i = selected.length - 1; i >= 0; i--)  
  111.                 {  
  112.                     model.removeRow(selected[i]);  
  113.                 }  
  114.             }  
  115.         });  
  116.         tableMenu.add(removeRowsItem);  
  117.  
  118.         mainWin.pack();  
  119.         mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  120.         mainWin.setVisible(true);  
  121.     }  
  122.  
  123.     public static void main(String[] args)   
  124.     {  
  125.         new TestDefaultTableModel().init();  
  126.     }  

但要注意列的增加,只是将原来隐藏的列显示,而不是真正增加列,你要新增的话那就重新new个JTable

前面讲的表格,单元格都是字符串,这是由于我们传入的都是DefaultTableModel它最终调用toString方法来绘制表格,具体自定义单元格的方法如下,eg


  1. public class TestTableCellRenderer  
  2. {  
  3.     JFrame jf = new JFrame("使用单元格绘制器");  
  4.     JTable table;  
  5.     //定义二维数组作为表格数据  
  6.     Object[][] tableData =   
  7.     {  
  8.         new Object[]{"李清照" , 29 , "女" , new ImageIcon("icon/3.gif") , true},  
  9.         new Object[]{"苏格拉底"56 , "男" , new ImageIcon("icon/1.gif") , false},  
  10.         new Object[]{"李白"35 , "男" , new ImageIcon("icon/4.gif")  , true},  
  11.         new Object[]{"弄玉"18 , "女" , new ImageIcon("icon/2.gif")  , true},  
  12.         new Object[]{"虎头" , 2 , "男" , new ImageIcon("icon/5.gif") , true}  
  13.     };  
  14.     //定义一维数据作为列标题  
  15.     String[] columnTitle = {"姓名" , "年龄" , "性别" , "主头像" , "是否中国人"};  
  16.     public void init()  
  17.     {  
  18.         //以二维数组和一维数组来创建一个ExtendedTableModel对象  
  19.         ExtendedTableModel model = new ExtendedTableModel(columnTitle , tableData);  
  20.         //以ExtendedTableModel来创建JTable  
  21.         table = new JTable( model);  
  22.         table.setRowSelectionAllowed(false);  
  23.         table.setRowHeight(40);  
  24.         //获取第三列  
  25.         TableColumn lastColumn = table.getColumnModel().getColumn(2);  
  26.         //对第三列采用自定义的单元格绘制器  
  27.         lastColumn.setCellRenderer(new GenderTableCellRenderer());  
  28.  
  29.         //将JTable对象放在JScrollPane中,并将该JScrollPane放在窗口中显示出来  
  30.         jf.add(new JScrollPane(table));  
  31.         jf.pack();  
  32.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  33.         jf.setVisible(true);  
  34.     }  
  35.     public static void main(String[] args)   
  36.     {  
  37.         new TestTableCellRenderer().init();  
  38.     }  
  39. }  
  40.  
  41. class ExtendedTableModel extends DefaultTableModel  
  42. {  
  43.     //重新提供一个构造器,该构造器的实现委托给DefaultTableModel父类  
  44.     public ExtendedTableModel(String[] columnNames , Object[][] cells)  
  45.     {  
  46.         super(cells , columnNames);  
  47.     }  
  48.     //重写getColumnClass方法,根据每列的第一个值来返回其真实的数据类型  
  49.     public Class getColumnClass(int c)   
  50.     {  
  51.         return getValueAt(0 , c).getClass();  
  52.     }  
  53. }  
  54.  
  55. class GenderTableCellRenderer extends JPanel implements TableCellRenderer  
  56. {  
  57.     private String cellValue;  
  58.     //定义图标的宽度和高度  
  59.     final int ICON_WIDTH = 23;  
  60.     final int ICON_HEIGHT = 21;  
  61.     public Component getTableCellRendererComponent(JTable table, Object value,   
  62.         boolean isSelected, boolean hasFocus, int row, int column)  
  63.     {  
  64.         cellValue = (String)value;  
  65.         //设置选中状态下绘制边框  
  66.         if (hasFocus)  
  67.         {  
  68.             setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));  
  69.         }  
  70.         else 
  71.         {  
  72.             setBorder(null);  
  73.         }  
  74.         return this;  
  75.     }  
  76.     //重写paint方法,负责绘制该单元格内容  
  77.     public void paint(Graphics g)  
  78.     {  
  79.         //如果表格值为"男"或"male",则绘制一个男性图标  
  80.         if (cellValue.equalsIgnoreCase("男")   
  81.             || cellValue.equalsIgnoreCase("male"))  
  82.         {  
  83.             drawImage(g , new ImageIcon("icon/male.gif").getImage());   
  84.         }  
  85.         //如果表格值为"女"或"female",则绘制一个女性图标  
  86.         if (cellValue.equalsIgnoreCase("女")   
  87.             || cellValue.equalsIgnoreCase("female"))  
  88.         {  
  89.             drawImage(g , new ImageIcon("icon/female.gif").getImage());   
  90.         }  
  91.     }  
  92.     //绘制图标的方法  
  93.     private void drawImage(Graphics g , Image image)  
  94.     {  
  95.         g.drawImage(image, (getWidth() - ICON_WIDTH ) / 2   
  96.             , (getHeight() - ICON_HEIGHT) / 2 , null);  
  97.     }  

我这里只是实现了每列不同的控件,大家还可以自定义一个表格每行每列都是不同的控件,那就要得到单元格再setCellRender。

原文链接:http://blog.****.net/terryzero/article/details/3838423

上一篇:Java性能优化常识


下一篇:《大数据分析原理与实践》一一第1章 绪  论 1.1 什么是大数据