2016-10-22 72 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字面值。