JTable with Customized AbstractTableModel

Joe

Thành viên VIP
21/1/13
3,074
1,344
113
(Continue of HERE)

JTable with Customized AbstractTableModel

To represent a series of something JTable is the most preferred choice. Especially when you work with data of similar objects from a Database. JTable is relatively easy to design. It's sufficient with an array of rows and an array of columns. Example:
Java:
public class TableExample {
  TableExample(){
    JFrame f=new JFrame();
    String data[][]={
                      {"101","Amit","670000"},
                      {"102","Jai","780000"},
                      {"101","Sachin","700000"}
                    };
    String column[]={"ID","NAME","SALARY"};   
    JTable jt=new JTable(data,column);
    jt.setBounds(30,40,200,300);    
    JScrollPane sp=new JScrollPane(jt);
    f.add(sp);    
    f.setSize(300,400);
    f.setVisible(true);
  }
  public static void main(String[] args) {
      new TableExample();
  }
}
Source: HERE. And the GUI looks quite nice.

1630767724774.png

Depending on what purpose you are working with JTable can be attached to a ListSelectionListener: the whole row or single cell when it is selected (i.e. click-on). I won't go into details because you could learn more from the given link. And a cell can be either a String (as usually) or any Object that could be an Icon or any Swing Component. For example, if the object is a JButton or JTextField this object can have its own Listener (e.g. ActionListener) either. Example: we modify the codes above:
Java:
// Joe Nartca (C)
public class JTableExample extends JFrame implements ActionListener {
  public static void main(String[] a) {
    new JTableExample();
  }
  public JTableExample() {
    setTitle("JTable Example");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // create a JButton with this ActionListener
    JButton jai = new JButton("Jai");
    jai.addActionListener(this);
    //
    String data[][]={ {"101","Amit","670000"},
                      {"102",jai.getText()+"_JButton","780000"},
                      {"101","Sachin","700000"}};
    String column[]={"ID","NAME","SALARY"};   
    JTable table = new JTable(data,column);
    table.setCellSelectionEnabled(true);
    ListSelectionModel select = table.getSelectionModel();
    select.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    select.addListSelectionListener(e -> {
      int r = table.getSelectedRow();
      int c = table.getSelectedColumn();
      String obj = (String)table.getValueAt(r, c);
      if (!"Jai_JButton".equals(obj)) return;
      ActionListener al[] = jai.getActionListeners();
      for(ActionListener a: al) { // execute the implemented ActionListener
        a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
      }
    });
    JScrollPane sp = new JScrollPane(table);
    add(sp);
    setSize(300, 200);
    setVisible(true);
  }
  public void actionPerformed(ActionEvent a) {
    JOptionPane.showMessageDialog(this, "JButton Jai was clicked", "INFO", JOptionPane.INFORMATION_MESSAGE);
  }
}
And the result is:

JTableExample.png

Everything is good as long as you are satisfied with all the "built-in" defaults of JTable. But if more specific requirements are needed you have no other choice than to customize some of these built-in defaults. For example: getRows() to return rows[][], updateModel(rows[][]) to replace all rows or even to create a model without a row. And the DefaultTableModel won't give you these features. In this case you have to create your own ListTableModel for your purpose. Here too, you can implement whatever you want in the cells as I showed you above with the JButton (represented by the text "Jai_JButton" or itself as an object). Further, as you have probably noticed in the above modified codes that I haven't complicated the matter with whatever complex TableCellRenderer as you could find on the Web, but just a simple String-Comparison for the necessary evaluation of an exact ActionListener execution.
Java:
   String obj = (String)table.getValueAt(r, c);
   if (!"Jai_JButton".equals(obj)) return;
   ActionListener al[] = jai.getActionListeners();
   for(ActionListener a: al) {
     a.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null) {
       // execute the implemented actionListener: see implementation
     });
   }
Simplicity is the best coding technique...exactly as Master Kalashnikov once said:

1630768012122.png

For the Boutique model I have added and impoved some methods to suit my purpose.
Java:
// Joe Nartca (c)
public class ListTableModel extends AbstractTableModel {
  // Constructor.
  public ListTableModel(String rows[][], String cols[]) throws Exception {
    super( );
    this.cols = cols;
    this.rows = rows;
  }
  public String getColumnName(int index) {
    return cols[index];
  }
  public int getRowAt(String name) {
    for (int i = 0; i < rows.length; ++i) {
      if (rows[i][0].equals(name)) return i;
    }
    return -1;
  }
  public void updateRow(String[] row, int r) {
    if (r >= 0 && r < rows.length) {
      rows[r] = row;
      fireTableRowsUpdated(r, r);
    }
  }
  public void removeRow(int row) {
    if (row < 0) return;
    if (rows.length == 1) {
      rows = new String[0][];
    } else {
      int len = rows.length-1;
      String[][] tmp = new String[len][];
      System.arraycopy(rows, 0, tmp, 0, row);
      if (row < len) System.arraycopy(rows, row+1, tmp, row, len-row);
      rows = tmp;
    }
    fireTableRowsDeleted(row, row);
  }
  public String[][] getRows() {
    return rows;
  }
  public void updateModel(String[][] tmp) {
    if (tmp != null) {
      rows = tmp;
      fireTableRowsUpdated(0, rows.length-1);
    }
  }
  public void addRow(String row[]) {
    int r = 0;
    if (rows.length == 0) {
      rows = new String[1][];
    } else {
      r = rows.length;
      String[][] tmp = new String[r+1][];
      System.arraycopy(rows, 0, tmp, 0, r);
      rows = tmp;
    }
    rows[r] = row;
    fireTableRowsInserted(r, r);
  }
  public int getRowCount() {
    if (rows == null) {
      rows = new String[0][];
      return 0;
    }
    return rows.length;
  }
  public int getColumnCount() {
    return cols.length;
  }
  public String getValueAt(int row, int column) {
    if (row < 0 || column < 0 || row > rows.length || column > cols.length) return "";
    return rows[row][column];
  }
  //
  private String cols[];
  private String rows[][];
}
(continue HERE)
 
Sửa lần cuối: