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)
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
É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
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