2016-10-22 70 views
0

TableModelListener(第87行/ HERE-1)是否干擾我的JTable的addRow方法(第139行,HERE-2)?如果是的話,我該如何解決它?TableModelListener和addRow干擾JTable/DefaultTableModel

此代碼將編譯,但是當我使用「添加行」按鈕時會引發錯誤。 錯誤是: (堆棧跟蹤時間更長,但我已將它縮減到關於我的類而不是java API的行)

線程「AWT-EventQueue-0」java.lang中的異常。 ArrayIndexOutOfBoundsException異常:

在HPLC.addRow(HPLC.java:142)

在HPLC.lambda $新的$ 1(HPLC.java:109)

這僅是一個問題,因爲我已經添加TableModelListener。

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

class HPLC extends JFrame 
{ 
    public static void main (String [] args) 
    { 
     new HPLC(); 
    } 
    HPLC() 
    { 
     //create window 
     JFrame frame = new JFrame(); 
     frame.setTitle("HPLC Calculator"); 
     frame.setSize(500,750); 
     frame.setResizable(false); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JPanel panel = new JPanel(); 
     panel.setLayout(new GridBagLayout()); 

     //row 0 
     JLabel title = new JLabel("HPLC Gradient Calculator"); 
     gridBagAdd(panel, title, 0,0,4,1, GridBagConstraints.CENTER); 

     //row 1 
     JLabel flowLabel = new JLabel("Flow rate"); 
     gridBagAdd(panel, flowLabel, 0,1,1,1, GridBagConstraints.CENTER); 

     JTextField flow = new JTextField(5); 
     gridBagAdd(panel, flow, 1,1,1,1, GridBagConstraints.CENTER); 

     JLabel mlMinLabel = new JLabel("ml/min"); 
     gridBagAdd(panel, mlMinLabel, 2,1,1,1, GridBagConstraints.CENTER); 

     //row 2 
     JLabel numInjLabel = new JLabel("Number of injections"); 
     gridBagAdd(panel, numInjLabel, 0,2,1,1, GridBagConstraints.CENTER); 

     JTextField numInj = new JTextField(5); 
     gridBagAdd(panel, numInj, 1,2,1,1, GridBagConstraints.CENTER); 

     //row 3 
     JLabel volALabel = new JLabel("Volume of A"); 
     gridBagAdd(panel, volALabel, 0,3,1,1, GridBagConstraints.CENTER); 

     JTextField volA = new JTextField(5); 
     volA.setEditable(false); 
     gridBagAdd(panel, volA, 1,3,1,1, GridBagConstraints.CENTER); 

     JLabel volBLabel = new JLabel("Volume of B"); 
     gridBagAdd(panel, volBLabel, 2,3,1,1, GridBagConstraints.CENTER); 

     JTextField volB = new JTextField(5); 
     volB.setEditable(false); 
     gridBagAdd(panel, volB, 3,3,1,1, GridBagConstraints.CENTER); 

     //row 4 
     JButton calculate = new JButton("calculate"); 
     gridBagAdd(panel, calculate, 0,4,1,1, GridBagConstraints.CENTER); 

     JButton addRow = new JButton("add row"); 
     gridBagAdd(panel, addRow, 1,4,1,1, GridBagConstraints.CENTER); 

     JButton removeRow = new JButton("remove row"); 
     gridBagAdd(panel, removeRow, 2,4,1,1, GridBagConstraints.CENTER); 

     //the gradient table 
     String[] columns = {"Time", "%A", "%B"}; 
     DefaultTableModel model = new DefaultTableModel(columns, 2) 
     { 
      public boolean isCellEditable(int row, int column) 
      //this overrides the default method to suit these conditions to make the 3rd column read only 
      { 
       if (column == 2) 
        return false; 
       return true; 
      } 
     }; 
     JTable table = new JTable(model); 
     table.setFillsViewportHeight(true); 
     JScrollPane tablePane = new JScrollPane(table); 
     gridBagAdd(panel, tablePane, 0,5,4,4, GridBagConstraints.CENTER); 
     table.getModel().addTableModelListener(new TableModelListener() 
    //HERE-1 { 
       public void tableChanged(TableModelEvent e) 
       //overriding the TableModelListener method 
       { 
        //the basics in order to get the table cell 
        int row = e.getFirstRow(); 
        int column = e.getColumn(); 
        TableModel model = (TableModel)e.getSource(); 
        String ColumnName = model.getColumnName(column); 
        Object data = model.getValueAt(row, column); 

        //what i do with that cell 
        volB.setText(data.toString()); 
       } 
      }); 

     //button methods 
     calculate.addActionListener(e -> calculate(model, volA)); 
     addRow.addActionListener(e -> addRow(model)); 
     removeRow.addActionListener(e -> removeRow(model)); 

     //make visible 
     frame.add(panel); 
     frame.setVisible(true); 
    } 
    //method for placement of components 
    private void gridBagAdd(JPanel p, JComponent c, int x, int y, int width, int height, int align) 
    { 
     GridBagConstraints gc = new GridBagConstraints(); 
     gc.gridx = x; 
     gc.gridy = y; 
     gc.gridwidth = width; 
     gc.gridheight = height; 
     gc.weightx = 100; 
     gc.weighty = 100; 
     gc.insets = new Insets(5,5,5,5); 
     gc.anchor = align; 
     gc.fill = GridBagConstraints.NONE; 
     p.add(c, gc); 
    } 
    //button method execution 
    private void calculate(DefaultTableModel model, JTextField volA) 
    { 
      int rowCount = model.getRowCount(); 
      String msg = rowCount + " rows"; 
      volA.setText(msg); 
    } 
    private void addRow(DefaultTableModel model) 
    { 
     int colCount = model.getColumnCount(); 
//HERE-2 Object [] newRow = new Object[colCount]; 
     model.addRow(newRow); 
    } 
    private void removeRow(DefaultTableModel model) 
    { 
     int rowCount = model.getRowCount(); 
     if (rowCount > 2) 
      model.removeRow(rowCount -1); 
    } 
} 

我希望我的表做的是創建一個基於表內容的數組,以執行計算。 TableModelListener已添加,因此%B列將自動完成以提供總計100%。

我自學成才,這是第一次有人見過我的任何代碼。如果您對如何改進寫作方法有任何建議,我很樂意聽到。

+0

*「如果你有關於如何提高我的寫作方法,任何意見我會很高興聽到它。「*請參閱http://codereview.stackexchange.com/。 –

+0

感謝您的聯繫,這將是無價的 –

回答

2

的TableModelListener已添加,以便%B列將自動完成,以總共得到100%

本次活動將告訴你它爲什麼產生。它看起來像你只想在單元格中改變一個值時執行你的代碼。

因此,代碼應該是這樣的:

public void tableChanged(TableModelEvent e) 
{ 
    if (e.getType() == TableModelEvent.UPDATE) 
    { 
     // add processing here 
    } 
} 

對於工作示例檢查:JTable -> TableModeListener

+0

問題已解決,但我仍然不完全確定爲什麼。 TableModelEvent.UPDATE僅查找單元格中的更改,而不是整個表格嗎? –

+0

就像一個MouseEvent。你有一個代碼告訴你事件產生的原因(「按下」或「釋放」)。那麼'TableModelEvent'也可以由於多種原因生成 - 改變單元格中的數據,添加一行,刪除一行。閱讀'TableModelEvent' API以獲取更多信息。 – camickr

2

您正在添加一個新行,因此TableModelListener將在您的事件中爲column屬性返回ALL_COLUMNS常量,該值爲-1 reference

int column = e.getColumn(); // here 

,然後試圖在這裏使用值-1:

Object data = model.getValueAt(row, column); 

這顯然是行不通的。

解決方案:在使用它之前,請檢查偵聽器中的列值。也許你會想爲你的列值使用一個int字面值。