2016-10-22 2 views
0

TableModelListener (ligne 87/HERE-1) interfère-t-elle avec ma méthode addRow (ligne 139, HERE-2) pour mon JTable? Si oui, comment le réparer?TableModelListener et addRow interférences dans JTable/DefaultTableModel

Ce code est compilé mais une erreur est générée lorsque j'utilise le bouton "Ajouter une ligne". L'erreur est: (la trace de la pile est beaucoup plus longue, mais je l'ai réduit à la ligne en ce qui concerne ma classe et non l'API java)

Exception dans le thread « AWT-EventQueue-0 » java.lang. ArrayIndexOutOfBoundsException:

à HPLC.addRow (HPLC.java:142)

à HPLC.lambda $ nouveau $ 1 (HPLC.java:109)

Cela n'a été un problème depuis que je l'ai ajouté le 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); 
    } 
} 

Ce que je voudrais ma table à faire, est de créer un tableau en fonction du contenu de la table, afin d'effectuer un calcul. Le TableModelListener a été ajouté afin que la colonne% B se termine automatiquement pour donner un total de 100%.

Je suis autodidacte et c'est la première fois que quelqu'un a jamais vu mon code. Si vous avez des conseils sur la façon d'améliorer ma méthode d'écriture, je serais heureux de l'entendre.

+0

* "Si vous avez des conseils sur la façon d'améliorer ma méthode d'écriture, je serais heureux pour l'entendre. "* Voir http://codereview.stackexchange.com/ pour cela. –

+0

Merci pour le lien, ce sera inestimable –

Répondre

2

Le TableModelListener a été ajouté afin que la colonne% B sera automatiquement complet pour donner un total de 100%

L'événement vous dira pourquoi il a été généré. Il me semble que vous ne voulez exécuter votre code que lorsque vous modifiez une valeur dans une cellule.

Ainsi, le code doit être quelque chose comme:

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

Pour un exemple de travail consulter: JTable -> TableModeListener

+0

Le problème est résolu, mais je ne suis pas encore tout à fait sûr pourquoi. TableModelEvent.UPDATE recherche-t-il uniquement les modifications dans la cellule par opposition à la table entière? –

+0

C'est comme un MouseEvent. Vous avez un code qui vous indique la raison pour laquelle l'événement a été généré ("pressé" ou "libéré"). Eh bien, un 'TableModelEvent' peut également être généré pour plusieurs raisons - en changeant des données dans une cellule, en ajoutant une ligne, en supprimant une ligne.Lisez l'API 'TableModelEvent' pour plus d'informations. – camickr

2

Vous ajoutez une nouvelle ligne et ainsi TableModelListener renvoie la constante ALL_COLUMNS dans votre événement pour la propriété column, une valeur qui est -1 reference.

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

puis essayer d'utiliser cette valeur -1 ici:

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

qui, évidemment, ne fonctionnera pas.

La solution: vérifiez la valeur des colonnes dans votre écouteur avant de l'utiliser. Peut-être voudrez-vous utiliser un littéral int pour votre valeur de colonne.