0

J'ai des problèmes avec le gestionnaire de sélection pour un JTable.Lors de la sélection de la ligne 0 dans JTable, le gestionnaire de sélection devient fou

La table est mise à jour toutes les 15 secondes à partir d'un thread d'actualisation dans le contrôle.

Je veux sélectionner une ligne dans mon JTable et extraire un contenu de colonne que je vais utiliser pour construire un nom de fichier.

Tant que la ligne 0 n'est pas sélectionnée pendant un rafraîchissement, tout fonctionne bien. Mais si la ligne 0 est sélectionnée lorsque l'actualisation est déclenchée, il semble qu'elle saute entre la procédure setAppserverData et le gestionnaire d'événements jusqu'à ce qu'elle dépasse le rowCount de la table et que j'obtienne une exception IndexOutOfBoundsException. Je suis un newbee Java et c'est sur le bord de mes connaissances, donc j'ai du mal à comprendre ce qui ne va pas avec le code. Mon intuition est que cela a quelque chose à voir avec moi en essayant de parvenir à une structure MVC et je ne parviens pas à séparer le code de la bonne façon.

// Le contrôleur

// Appserver worker 
class AppserverWorker extends SwingWorker<Integer, Integer>{ 
    protected Integer doInBackground() throws Exception{ 

     // Check appservers 
     while(true){ 
      theModel.readAppservData(); 

      // Update action buttons 
      try { 
       if(!theModel.isStatusOk()){ 
        theGui.actionButtonPanel.setAppServBtnColor("RED"); 
        //    theGui.actionButtonPanel.setButtonFlashOn(); 
       }else theGui.actionButtonPanel.setAppServBtnColor("GREEN"); 
      } catch (IllegalArgumentException e1) { 
       sysLogger.logMsg("SEVERE",e1.getMessage()); 
       JOptionPane.showMessageDialog(null, e1.getMessage()); 
      } 

      // Update GUI 
      theGui.extAppServPanel.setAppserverData(theModel.getAppservData()); 

      // Sleep refresh time 
      // TODO read refresh from init table 
      try { 
       Thread.sleep(appServRefreshTime); 
      } catch (InterruptedException e) {} 
     } 
    } 

// List selection handler 
class SharedListSelectionHandler implements ListSelectionListener { 
    public void valueChanged(ListSelectionEvent e) { 
     if (!e.getValueIsAdjusting()){     // To avoid double trigger of listener 
      System.out.println(">>>>>>>>> Selection list handler >>>>>>>>"); 
      String fileName = null; 
      String fileExt = ".txt"; 
      ListSelectionModel lsm = (ListSelectionModel)e.getSource(); 
      try {  
       int selectedRow = lsm.getAnchorSelectionIndex();        // Get the row clicked 
       if (selectedRow>=0){               // If -1 no row selected 
        fileName = theGui.extAppServPanel.getAppservName(selectedRow)+fileExt;  // Get appserver name and build file name 
        theModel.readCollectFile(InitParameters.collectFilePath, fileName);   // Read collect file 
        theGui.extAppServPanel.setAppservInfo(theModel.getCollectFileContent()); // Fill the text panel with collect file 
       } 
      } 
      catch(FileNotFoundException e1){ 
       sysLogger.logMsg("SEVERE",this.getClass().getSimpleName()+": Collect file "+fileName+" is missing"); 
       JOptionPane.showMessageDialog(null, "Collect file "+fileName+" is missing"); 
      } 

      catch(IOException e1){ 
       sysLogger.logMsg("SEVERE",this.getClass().getSimpleName()+": System error: An I/O error occurred"); 
       System.err.println("System error: An I/O error occurred"); 
       System.exit(0);; 
      } 
     } 
    } 
} 

// La vue

public class ExtAppServPanel extends JPanel { 

private JTable table; 
private DefaultTableModel model; 

private JTextArea textAreaInfo; 
private JButton btnSaveInfo; 
private List colData; 

public boolean ignoreTableChanges = false; 

/** 
* Constructor 
*/ 
public ExtAppServPanel() { 
    System.out.println(this.getClass().getSimpleName()+": Constructor"); 

    setLayout(new MigLayout("", "[350:376.00,grow,leading]", "[100px:100,grow][][48.00,grow][]")); 
    this.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "Application servers info", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0))); 

    // Set up table 
    String[] columnNames = {"Server name", "Type","Status"}; 
    model = new DefaultTableModel(null,columnNames); 
    table = new JTable(model){ 

     // Color code rows 
     @Override 
     public Component prepareRenderer(TableCellRenderer renderer, int row, int col) { 
      Component comp = super.prepareRenderer(renderer, row, col); 

      if (!isRowSelected(row)){ 
       comp.setBackground(getBackground()); 
       int modelRow = convertRowIndexToModel(row); 
       String type = (String)getModel().getValueAt(modelRow, 2); 
       if ("FAIL".equals(type)) comp.setBackground(Color.RED); 
       if ("WARNING".equals(type)) comp.setBackground(Color.YELLOW); 
      } 
      return comp; 
     } 
    }; 

    // Set grid 
    table.setGridColor(Color.LIGHT_GRAY); 

    // Set width and alignment 
    table.getColumnModel().getColumn(1).setMinWidth(200); 
    table.getColumnModel().getColumn(1).setMaxWidth(200); 
    table.getColumnModel().getColumn(1).setPreferredWidth(200); 

    table.getColumnModel().getColumn(2).setMinWidth(75); 
    table.getColumnModel().getColumn(2).setMaxWidth(75); 
    table.getColumnModel().getColumn(2).setPreferredWidth(75); 


    // Add scrollpane 
    JScrollPane scrollPane = new JScrollPane(table); 
    scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); 
    scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); 
    table.setFillsViewportHeight(true); 
    this.add(scrollPane, "cell 0 0,grow"); 

    // Set up text area 
    JLabel lblDetails = new JLabel("Details"); 
    this.add(lblDetails, "cell 0 1,alignx leading"); 

    textAreaInfo = new JTextArea(); 
    textAreaInfo.setBackground(Color.BLACK); 
    textAreaInfo.setForeground(Color.GREEN); 
    textAreaInfo.setEditable(false); 
    textAreaInfo.setFont(new Font("Lucida Console",Font.PLAIN,10)); 

    JScrollPane scrollPane_1 = new JScrollPane(); 
    scrollPane_1.setViewportView(textAreaInfo); 
    this.add(scrollPane_1, "cell 0 2,grow"); 

    // Save button 
    btnSaveInfo = new JButton("Save"); 
    add(btnSaveInfo, "cell 0 3,alignx right"); 
} 

/* 
* Setters and getters 
*/ 
public void setAppserverData(ArrayList<ArrayList<String>> dataRecord) { 
    ArrayList<String> dataCol = new ArrayList<String>(); 

    // Init values array from result set 
    try { 
     model.setRowCount(0); // <<<<<<<<<< Problem 
     String[] arrayRow; 
     String status = "Ok"; 

     // Get first row from list 
     dataCol = dataRecord.get(0);      
     arrayRow = new String[dataCol.size()]; 
     arrayRow[0] = dataCol.get(2); 
     arrayRow[1] = dataCol.get(1); 
     arrayRow[2] = dataCol.get(4); 

     for (int i = 0; i < dataRecord.size(); i++){ 
      dataCol = dataRecord.get(i); 

      // Check status 
      if (dataCol.get(4).toUpperCase().equals("FAIL")){ 
       status = "FAIL"; 
      }else if (dataCol.get(4).toUpperCase().equals("WARNING")){ 
       status = "WARNING"; 
      } 

      if (!dataCol.get(2).toUpperCase().equals(arrayRow[0].toUpperCase())){ 
       arrayRow[2] = status;       // Override status 
       System.out.println(">>>>>>>>> Updating table >>>>>>>>"); 
       model.addRow(arrayRow);       // Add row to table 
       arrayRow = new String[dataCol.size()]; 
       arrayRow[0] = dataCol.get(2); 
       arrayRow[1] = dataCol.get(1); 
       arrayRow[2] = dataCol.get(4); 
       status = "Ok"; 
      } 
     } 
     setAppservName(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

// Get row count 
public int getRowCount(){ 
    return model.getRowCount(); 
} 

// Set table data 
public void setAppservName(){ 
    Vector data = model.getDataVector(); 
    Vector row = (Vector) data.elementAt(1); 

    // Copy the first column 
    int mColIndex = 0;- 
    colData = new ArrayList(table.getRowCount()+1); 

    for (int i = 0; i < table.getRowCount(); i++) { 
     row = (Vector) data.elementAt(i); 
     colData.add(row.get(mColIndex)); 
    } 
} 

// Get table data 
public String getAppservName(int rowNum){ 
    return (String) colData.get(rowNum); 
} 

// Set appserver info 
public void setAppservInfo(String appservInfo){ 
    textAreaInfo.setText(appservInfo); 
    textAreaInfo.setCaretPosition(0);  // Set cursor at top of text 
} 

// Get appserver info 
public String getAppservInfo(){ 
    return textAreaInfo.getText(); 
} 

/** 
* Action listeners 
*/ 

public void addTableRowListener(ListSelectionListener listSelectionEvent) { 
    table.getSelectionModel().addListSelectionListener(listSelectionEvent); 
} 

public void addButtonListener(ActionListener buttonEvent) { 
    btnSaveInfo.addActionListener(buttonEvent); 
    btnSaveInfo.setActionCommand("saveAppServInfo"); 
} 

}

de sortie de trace lorsqu'une ligne non zéro est sélectionné et que le fil de rafraîchissement est exécuté

** Appserver worker ** 
CmtModel: readAppservData 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>> Rowcount = 8 

sortie de trace lorsque la ligne zéro est sélectionné et que le fil de rafraîchissement est exécutée

** Appserver worker ** 
CmtModel: readAppservData 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 0 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 1 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 2 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 3 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 4 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 5 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 6 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 7 << 
>>>>>>>>> Updating the table >>>>>>>> 
>>>>>>>>> Selection list handler ! >>>>>>>> 
>> Controll: selectedRow = 8 << 
java.lang.IndexOutOfBoundsException: Index: 8, Size: 8 
    at java.util.ArrayList.rangeCheck(Unknown Source) 
    at java.util.ArrayList.get(Unknown Source) 
    at panels.ExtAppServPanel.getAppservName(ExtAppServPanel.java:219) 
    at Control$SharedListSelectionHandler.valueChanged(Control.java:330) 
    at javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source) 
    at javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source) 
    at javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source) 
    at javax.swing.DefaultListSelectionModel.insertIndexInterval(Unknown Source) 
    at javax.swing.JTable.tableRowsInserted(Unknown Source) 
    at javax.swing.JTable.tableChanged(Unknown Source) 
    at javax.swing.table.AbstractTableModel.fireTableChanged(Unknown Source) 
    at javax.swing.table.AbstractTableModel.fireTableRowsInserted(Unknown Source) 
    at javax.swing.table.DefaultTableModel.insertRow(Unknown Source) 
    at javax.swing.table.DefaultTableModel.addRow(Unknown Source) 
    at javax.swing.table.DefaultTableModel.addRow(Unknown Source) 
    at panels.ExtAppServPanel.setAppserverData(ExtAppServPanel.java:172) 
    at Control$AppserverWorker.doInBackground(Control.java:434) 
    at Control$AppserverWorker.doInBackground(Control.java:1) 
    at javax.swing.SwingWorker$1.call(Unknown Source) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at javax.swing.SwingWorker.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
+0

Vous mettez constamment à jour votre table, ce qui va nuire au traitement de votre sélection. Vous vivez également les règles du fil unique de Swing sur plusieurs instances – MadProgrammer

+0

Évidemment, je dois creuser plus profondément dans la gestion des threads, mais qu'en est-il de la mise à jour de la table? – Magher

+0

Votre 'SwingWorker' devrait utiliser la fonctionnalité' publish'/'process' pour envoyer des mises à jour à l'interface utilisateur. Ce que vous envoyez dépendra de la façon dont vous voulez l'atteindre. Jetez un coup d'oeil de plus près à [Worker Threads et SwingWorker] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) pour plus de détails – MadProgrammer

Répondre

2
// Update GUI 
theGui.extAppServPanel.setAppserverData(theModel.getAppservData()); 

Ne pas mettre à jour le modèle ou l'interface utilisateur graphique dans le procédé doInBackground().

Toutes les mises à jour de l'interface graphique doivent être effectuées sur le EventDispatchThread (EDT). Au contraire, lorsque les données changent, vous devez "publier" les résultats afin que le code puisse être exécuté dans la méthode process(...) du SwingWorker qui s'exécute sur l'EDT et par conséquent l'interface graphique sera mise à jour sur l'EDT.

Lisez la section du tutoriel Swing sur Concurrency pour plus d'informations. La section sur Tasks That Have Intermediate Results a un exemple de l'approche de publication.