在JTable中选择第0行时,选择处理程序会发疯

时间:2015-11-30 16:53:47

标签: java swing model-view-controller jtable listselectionlistener

我遇到了JTable选择处理程序的问题。

该表每15秒从Control中的刷新线程更新一次。

我想在JTable中选择一行并提取我将用于构建文件名的列内容。

只要在刷新期间未选择第0行,一切正常。但是如果在触发刷新时选择了第0行,它看起来像是在setAppserverData过程和事件处理程序之间跳转,直到它超过表的rowCount并且我得到一个IndexOutOfBoundsException。

我是一个Java新手,这是我所知的边缘,所以我很难搞清楚代码有什么问题。我的直觉是,它与我试图实现MVC结构有关,而且我无法以正确的方式分离代码。

//控制器

// 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);;
            }
        }
    }
}

//视图

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");
}

}

选择非零行并运行刷新线程时的跟踪输出

** 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

选择零行并运行刷新线程时的跟踪输出

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

1 个答案:

答案 0 :(得分:2)

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

不要在doInBackground()方法中更新模型或GUI。

GUI的所有更新都应在EventDispatchThread (EDT)

上完成

相反,当数据发生变化时,您需要&#34;发布&#34;结果所以代码可以在process(...)的{​​{1}}方法中执行,该方法在EDT上执行,因此GUI将在EDT上更新。

阅读Concurrency上Swing教程中的部分以获取更多信息。 SwingWorker部分有一个发布方法示例。