关于JTable的使用
JTable是个JavaSwing中的表格控件,可以用来显示数据和编辑数据。这里讲一下我的使用心得。
JavaSwing讲究MVC理念,而这个JTable也可以说是个迷你的MVC模型。JTable只是个显示数据的表格,而它的数据其实是在TableModel上的。每一个Jtable都会有自己的TableModel。可以这样想,你实现好了tableModel的方法,就可以自动生成表格。
有两种方法设置JTable的model:
//这个TableDataModel是实现了TableModel的类 TableDataModel tableModel = new TableDataModel(); JTable jTable = new JTable(tableModel);//1 jTable.setModel(tableMoedl);
当然,我们一般不会自己去实现这个接口,Java提供了两个实现了这个接口的类:
AbstractTableModel, DefaultTableModel 也就是说我们在在写自己的TableModel的时候只要extends他们就行了。
这里我们主要看看AbstractTableModel
这个类基本实现了TableModel接口的方法,但有几个我们还是一定要重写的:
public int getRowCount();
public int getColumnCount();
public Object getValueAt(int row, int column);
这三个方法,大概就是用来生成表格的,前两个确定表格的行与列数。第三个是确定每个单元格格的值。
然后还有几个有用的方法:
isCellEditable(int rowIndex, int columnIndex)---------这个方法是让某个单元格可以编辑
public String getColumnName(int column)---------告诉表格列表名
setValueAt(Object aValue, int rowIndex, int columnIndex)------------如果你的表格是可以编辑的,那么一定要实现这个方法。它是什么效果呢?它可以在数据发生改变的时候重新设置该单元格的值。如果你不重写这个方法,当你改一个单元格的值,然后回车,它又会变回去。而且你改完后,获取到的值也是原来的。 因为这个JTable的数据都是放在TableModel中的,所以,要真正地改表格的值,就要改model的数据。 重写了这个方法后,编辑完后单元格后,就不会再变回去了。
现在来看一个例子的代码
package com.wangshen.www.service; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Vector; import javax.swing.table.AbstractTableModel; import com.wangshen.www.dao.CheckDao; /** * 这个类是表格的数据模型,用来实现表格的数据展示和数据管理 * @author 85060 * */ //一开始我特么rowData是个二维的vector,然年不知道为什么怎么重写那个setValueAt方法都做不到直接在表格上编辑,然后就换成了rowData里面装的每一行是字符串数组的形式 public class TableDataModel extends AbstractTableModel { Vector<String> columnData = new Vector<String>();//保存列名称 Vector rowData = null; public TableDataModel() { CheckDao checkDao = new CheckDao(); columnData.add("id"); columnData.add("书本名称"); columnData.add("书本价格"); columnData.add("收入时间"); columnData.add("是否借出(1代表已借出)"); rowData = checkDao.getRowData(); } @Override//必须要重写实现的 public int getColumnCount() { // TODO Auto-generated method stub return columnData.size(); } @Override//必须要重写实现的 public int getRowCount() { // TODO Auto-generated method stub return rowData.size(); } @Override//必须要重写实现的 public Object getValueAt(int row, int column) { // TODO Auto-generated method stub /* Vector temp=((Vector)rowData.get(row)); return temp.get(column); */ String LineTemp[] = (String[])rowData.get(row); return LineTemp[column]; } @Override public String getColumnName(int column) { // TODO Auto-generated method stub return (String)this.columnData.get(column); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { // TODO Auto-generated method stub if(columnIndex>0){ return true; } else{ return false; } } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { /* Vector temp = (Vector)rowData.get(rowIndex); switch(rowIndex) { case 1: //temp.setElementAt((String)aValue, 1); temp.set(1,(String)aValue); break; case 2: temp.setElementAt((float)aValue, 2); break; case 3: temp.setElementAt((String)aValue, 3); break; case 4: temp.setElementAt((Integer)aValue, 4); break; } */ // 当单元格的数据发生改变的时候掉用该函数重设单元格的数据 // 我们想一下,数据是放在TableData 中的,说白了修改数据就是修改的 // TableData中的数据,所以我们仅仅在此处将TableData的对应数据修改即可 ((String[])this.rowData.get(rowIndex))[columnIndex]=(String)aValue; super.setValueAt(aValue, rowIndex, columnIndex); // // 其实这里super的方法是调用了fireTableCellUpdated()只对应更新了 // 对应单元格的数据 // fireTableCellUpdated(rowIndex, columnIndex); } }
(补一下,这个Vector其实就是个列表一样的东西,实现了List,和ArrayList差不多,但是个动态数组)
然后来看看Dao层中row数据的获取
package com.wangshen.www.dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Vector; import com.wangshen.www.util.DbUtil; /** * 这个类是获取整个图书表的一个resultset * @author 85060 * */ public class CheckDao { DbUtil dbUtil = new DbUtil(); public Vector getRowData() {//返回一个Vector,就是一个表格的row信息 Connection con = dbUtil.getCon();//获取数据库连接 String sql = "SELECT * FROM t_books"; PreparedStatement pstmt = null; ResultSet rs = null; Vector rowData = new Vector();//用来保存数据库中的行结果 try { pstmt = con.prepareStatement(sql); rs = pstmt.executeQuery(); while(rs.next()) { //Vector hang=new Vector(); String[] temp = new String[50]; int i = 0; /* hang.add(rs.getInt("id")); hang.add(rs.getString("bookName")); hang.add(rs.getFloat("price")); hang.add(rs.getString("time")); hang.add(rs.getInt("status")); rowData.add(hang); */ temp[i++] = rs.getInt("id")+""; temp[i++] = rs.getString("bookName")+""; temp[i++] = rs.getFloat("price")+""; temp[i++] = rs.getString("time")+""; temp[i++] = rs.getInt("status")+""; rowData.add(temp); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("查找数据库行信息的数据库操作出错"); } finally { dbUtil.close(pstmt, con); } return rowData; } }
每个Vector变量(row的数据)里面是n个一维的字符串数组,代表着表格中的n行数据。
再来看JTable的建立
JPanel panelTable = new JPanel();//用来装表格的panel TableModel tableModel = new TableDataModel();//table模型,这就话同时初始化表格 JTable tableBooks = new JTable();//不要这里加model好,以后同步不方便…… //官方api建议我们这样做,就是用个有滚轮的Panel来装这个表格,就当做表格的一部分吧 JScrollPane scrollPane = new JScrollPane(tableBooks); scrollPane.setViewportView(tableBooks);//其实好像和那个构造方法的效果一样……但有 些例子加了就加吧…… panelTable.add(scrollPane); tableBooks.setFillsViewportHeight(true);//表格充满容器,不加这一句表格不会充满容器panelTable。(似乎scrollPane是跟着table一起充满panelTable)
然后关于其他操作,只要抓住表格显示的数据是TableModel里的数据这点就行了。
补充: 之前实现刷新,是重新搞个新的TableModel的实现对象,然后再
table.setModel
来实现表格的更新。 后面知道,你如果用的是Vector或者List,只要你重写好了TableModel里面需要重写的方法,你只需要在改变你的model里面的类变量,比如行数据rowData后,再调用
table.updateUi()
就可以实现表格的更新,效果还挺好!!