JTable 是我们一般展示数据的一个很好的Grid组建,个人认为在使用swing 组建时对其model的定义很重要,今天鄙人做了小小研究,定义了自己的TableModel,甚是高兴,于是分享出来与大家共同进步。
首先定义我们要展示的数据模型:
MyData.java
package table; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import table.MyTableDataModel.MyTableColumn; /** * My dataModel * @author Lyon Yao * */ public class MyData { private String name; private String sex; private String cellphone; private String address; private Boolean isSelected; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public Object isSelected() { return this.isSelected; } public void setSelected(Boolean value){ this.isSelected=value; } public HashMap<MyTableColumn, String> validate() { HashMap<MyTableColumn, String> result=new HashMap<MyTableDataModel.MyTableColumn, String>(0); if(this.name==null||this.name.isEmpty()){ result.put(MyTableColumn.NAME, "Please Input Name"); } if(!isNumeric(this.cellphone)){ result.put(MyTableColumn.CELLPHONE, "Please Input Correct CellPhone"); } return result; } public boolean isNumeric(String str) { Pattern pattern = Pattern.compile("[0-9]*"); Matcher isNum = pattern.matcher(str); if (!isNum.matches()) { return false; } return true; } }
然后去定义我的TableModel,比较扯,我将renderer和editor也在model里面做了关联定义,只在使用时候调用的。
MyTableDataModel.java
package table; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.HashMap; import java.util.List; import javax.imageio.ImageIO; import javax.swing.DefaultCellEditor; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JPanel; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; /** * this class is used to difine the table's model,in this class,we defined * column's cell editor and renderer * @author Lyon Yao * */ public class MyTableDataModel extends AbstractTableModel { /** * */ private static final long serialVersionUID = -7312994273683436365L; enum MyTableColumn implements ValueOperate{ IS_SELECTED(""){ @Override public Object getValue(MyData rowData) { return rowData.isSelected(); } @Override public void setValue(MyData rowData, Object obj) { rowData.setSelected(obj==null?false:Boolean.valueOf(obj.toString())); } @Override public TableCellEditor getCellEditor() { return new DefaultCellEditor(new JCheckBox()); } @Override public TableCellRenderer getCellRenderer() { return new TableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JCheckBox checkBox=new JCheckBox(); checkBox.setSelected((Boolean)value); return checkBox; } }; } @Override public int getMinWidth() { return 25; } @Override public int getMaxWidth() { return 25; } },NAME("Name"){ @Override public Object getValue(MyData rowData) { return rowData.getName(); } @Override public void setValue(MyData rowData,Object obj) { if(obj==null)return; rowData.setName(obj.toString()); } @Override public int getMinWidth() { return 100; } @Override public int getMaxWidth() { return 200; } },SEX("Sex"){ @Override public Object getValue(MyData rowData) { return rowData.getSex(); } @Override public void setValue(MyData rowData,Object obj) { rowData.setSex(obj==null?null:obj.toString()); } @Override public TableCellEditor getCellEditor() { JComboBox box=new JComboBox(); box.addItem("Male"); box.addItem("Famale"); return new DefaultCellEditor(box); } @Override public TableCellRenderer getCellRenderer() { return new TableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JComboBox box=new JComboBox(); box.addItem(value); box.setSelectedIndex(0); return box; } }; } @Override public int getMinWidth() { return 70; } @Override public int getMaxWidth() { return 120; } },CELLPHONE("Cellphone"){ @Override public Object getValue(MyData rowData) { return rowData.getCellphone(); } @Override public void setValue(MyData rowData,Object obj) { rowData.setCellphone(obj==null?null:obj.toString()); } @Override public int getMinWidth() { return 150; } @Override public int getMaxWidth() { return 150; } },ADRESS("Address"){ @Override public Object getValue(MyData rowData) { return rowData.getAddress(); } @Override public void setValue(MyData rowData,Object obj) { rowData.setAddress(obj==null?null:obj.toString()); } @Override public int getMinWidth() { return 200; } @Override public int getMaxWidth() { return 1000; } }; private final String name; private TableCellEditor editor; private TableCellRenderer renderer; private MyTableColumn(String name) { this.name = name; } @Override public void setCellEditor(TableCellEditor editor) { this.editor=editor; } @Override public void setCellRenderer(TableCellRenderer renderer) { this.renderer=renderer; } @Override public String toString() { return this.name; } @Override public TableCellEditor getCellEditor() { return this.editor; } @Override public TableCellRenderer getCellRenderer() { return this.renderer; } } interface ValueOperate{ Object getValue(MyData rowData); void setValue(MyData rowData,Object obj); TableCellEditor getCellEditor(); TableCellRenderer getCellRenderer(); void setCellEditor(TableCellEditor editor); void setCellRenderer(TableCellRenderer renderer); int getMinWidth(); int getMaxWidth(); } private final List<MyData> data; private static BufferedImage dash; static{ try { dash=ImageIO.read(MyTableDataModel.class.getClassLoader().getResources("table\\dash.png").nextElement()); } catch (IOException e) { e.printStackTrace(); } ; } public MyTableDataModel(List<MyData> data) { super(); this.data = data; setUpColumEidtors(); setUpColumnRenders(); } private void setUpColumEidtors(){ final DefaultCellEditor editor=new DefaultCellEditor(new JTextField()); for(MyTableColumn col:MyTableColumn.values()){ col.setCellEditor(editor); } } public void addItem(MyData data){ this.data.add(data); fireTableDataChanged(); } public void delete(MyData data){ if(data!=null){ this.data.remove(data); fireTableDataChanged(); } } public void delete(int index){ if(index>-1&&index<this.data.size()){ this.data.remove(index); fireTableDataChanged(); } } private void setUpColumnRenders(){ final DefaultTableCellRenderer renderer=new DefaultTableCellRenderer(){ /** * */ private static final long serialVersionUID = 2330186726723746657L; @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component component= super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); HashMap<MyTableColumn, String> errorData = isErrorData(row,column); if(!errorData.isEmpty()){ final JPanel panel=new JPanel(new BorderLayout()){ /** * */ private static final long serialVersionUID = -6170683167857459445L; @Override public void paint(Graphics g) { super.paint(g); final int cc=(int) Math.round((getWidth()*1.0/dash.getWidth())); for(int i=0;i<cc;i++){ g.drawImage(dash, i*dash.getWidth(), getHeight()-dash.getHeight(),null); } } }; panel.add(component); panel.setToolTipText(errorData.get(getColumnByIndex(column))); component=panel; } return component; } }; for(MyTableColumn col:MyTableColumn.values()){ col.setCellRenderer(renderer); } } private MyTableColumn getColumnByIndex(int column){ return MyTableColumn.values()[column]; } private HashMap<MyTableColumn,String> isErrorData(int row,int column){ MyData rowData=data.get(row); HashMap<MyTableColumn, String> result=new HashMap<MyTableDataModel.MyTableColumn, String>(0); HashMap<MyTableColumn, String> validte= rowData.validate(); for(MyTableColumn col:validte.keySet()){ if(col.ordinal()==column){ result.put(col, validte.get(col)); } } return result; } @Override public int getRowCount() { return this.data.size(); } @Override public int getColumnCount() { return MyTableColumn.values().length; } @Override public Object getValueAt(int rowIndex, int columnIndex) { MyData row=data.get(rowIndex); for(MyTableColumn column:MyTableColumn.values()){ if(column.ordinal()==columnIndex) return column.getValue(row); } return null; } @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) { MyData row=data.get(rowIndex); for(MyTableColumn column:MyTableColumn.values()){ if(column.ordinal()==columnIndex) column.setValue(row,aValue); } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } }
好了 核心的东西已经出来了,下面写个测试类玩玩:)
TableExample.java
package table; import java.awt.HeadlessException; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.WindowConstants; public class TableExample extends JFrame { /** * */ private static final long serialVersionUID = -5180906807674700787L; /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub new TableExample(); } private TableExample() throws HeadlessException { super(); this.setBounds(200, 200, 1024, 768); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); this.creatTable(); this.setVisible(true); } private void creatTable() { final List<MyData> data=new ArrayList<MyData>(0); MyData myData = new MyData(); myData.setName("xxxddd"); myData.setAddress("XXOOXXOO"); myData.setCellphone("11392901"); myData.setSex("Famale"); myData.setSelected(true); data.add(myData); myData = new MyData(); myData.setName("xxxddd"); myData.setAddress("XXOOXXOO"); myData.setCellphone("11392901"); myData.setSex("Famale"); myData.setSelected(true); data.add(myData); myData = new MyData(); myData.setName("xxxddd"); myData.setAddress("XXOOXXOO"); myData.setCellphone("11392901"); myData.setSex("Famale"); myData.setSelected(true); data.add(myData); JTable table=new JTable(new MyTableDataModel(data)); table.setRowHeight(20); for( MyTableDataModel.MyTableColumn column:MyTableDataModel.MyTableColumn.values()) { table.getColumnModel().getColumn(column.ordinal()).setHeaderValue(column); table.getColumnModel().getColumn(column.ordinal()).setCellEditor(column.getCellEditor()); table.getColumnModel().getColumn(column.ordinal()).setCellRenderer(column.getCellRenderer()); table.getColumnModel().getColumn(column.ordinal()).setMaxWidth(column.getMaxWidth()); table.getColumnModel().getColumn(column.ordinal()).setMinWidth(column.getMinWidth()); } JScrollPane panle=new JScrollPane(table); this.add(panle); } }
大功告成,试运行如图: