2013-01-24 30 views
1

我對SWING相當陌生,經過一些測試後,我決定使用CardLayout進行一個非常簡單的程序:我有3張卡片(一個用於登錄,一個用於添加數據,另一個用於顯示它)。 問題是我有一個在這些卡之間共享的列表(通過引用),它可以被多張卡修改。 出於某種原因,在我附近有一座小打,程序中斷在試圖遍歷列表,可以看到下面的錯誤:CardLayout + Concurrency

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException 
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819) 

沒有線程一邊修改列表或任何東西,所以我不確定爲什麼會出現異常。我甚至試圖同步在列表上運行的那部分代碼,但沒有好的結果。 我不完全確定,如果我自己清楚,請隨時提問。 (代碼不提供,因爲它不只是一個片段,但如果任何人發現它是必要的,我會把它)。

在此先感謝。

- 編輯 - 下面的代碼: 主類:

package cantodasletras.br.views; 

import java.awt.CardLayout; 

public class CantoDasLetrasMain { 

private JFrame frmCantodasletras; 
private static int DEBUG = 0; 
private final String LOGINMENU = "The user login view"; 
private final String MENUVIEW = "The user menu view"; 
private final String SEARCHVIEW = "The search view"; 
private final String ADDNEWVIEW = "The create new order view"; 

private ArrayList<Order> listOfOrders = null; 

private JPanel renderPanel; 


/** 
* Launch the application. 
*/ 
public static void main(final String[] args) { 
EventQueue.invokeLater(new Runnable() { 
    public void run() { 
    if (args.length > 0) 
     DEBUG = 1; 


    try { 
     CantoDasLetrasMain window = new CantoDasLetrasMain(); 
     window.frmCantodasletras.setVisible(true); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
}); 
} 

/** 
* Create the application. 
*/ 
public CantoDasLetrasMain() { 
    initialize(); 
} 

/** 
* Initialize the contents of the frame. 
*/ 
private void initialize() { 

listOfOrders = new ArrayList<Order>(); 

UIManager.put("Button.defaultButtonFollowsFocus", Boolean.TRUE); 
frmCantodasletras = new JFrame(); 
frmCantodasletras.setTitle("CantoDasLetras 1.0"); 
frmCantodasletras.setBounds(100, 100, 754, 530); 
frmCantodasletras.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frmCantodasletras.getContentPane().setLayout(null); 

renderPanel = new JPanel(); 
renderPanel.setBounds(0, 0, 738, 472); 
frmCantodasletras.getContentPane().add(renderPanel); 
renderPanel.setLayout(new CardLayout(0, 0)); 
CardLayout cl = (CardLayout) renderPanel.getLayout(); 

//Inicializar todas as views 

LoginView lv = new LoginView(cl,renderPanel); 
renderPanel.add(lv, LOGINMENU); 

MenuView mv = new MenuView(cl, renderPanel); 
renderPanel.add(mv,MENUVIEW); 

SearchView sv = new SearchView(cl,renderPanel,listOfOrders); 
renderPanel.add(sv,SEARCHVIEW); 

AddNewView anv = new AddNewView(cl, renderPanel,listOfOrders); 
renderPanel.add(anv,ADDNEWVIEW); 


    } 
} 

我這裏還有卡:

package cantodasletras.br.views; 

import java.awt.CardLayout; 

public class AddNewView extends JPanel { 

    private final String MENUVIEW = "The user menu view"; 
    private JTextField fieldNome; 
    private JTextField fieldTelefone; 
    private JTextField fieldLivro; 
    private JTextField fieldQuantidade; 
    private JTextField fieldData; 
    private JComboBox cBSit; 
    private JTextArea fieldObs; 

    /** 
    * Create the panel. 
    */ 
    public AddNewView(final CardLayout cl, final JPanel renderPanel, 
    final ArrayList<Order> orders) { 
    setLayout(null); 

    JButton btnNewButton = new JButton("Cancelar"); 
    btnNewButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     cl.show(renderPanel, MENUVIEW); 
     } 
    }); 
    btnNewButton.setBounds(541, 429, 89, 33); 
    add(btnNewButton); 

    JButton btnCadastrar = new JButton("Cadastrar"); 
    btnCadastrar.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 

     String nome = fieldNome.getText(); 
     String livro = fieldLivro.getText(); 
     String telefone = fieldTelefone.getText(); 
     String situacao = (String) cBSit.getSelectedItem(); 
     Integer quantidade = Integer.parseInt(fieldQuantidade.getText()); 
     String obs = fieldObs.getText(); 
     String data = fieldData.getText(); 

     fieldNome.setText(""); 
     fieldLivro.setText(""); 
     fieldTelefone.setText(""); 
     cBSit.setSelectedIndex(0); 
     fieldQuantidade.setText(""); 
     fieldObs.setText(""); 
     fieldData.setText(""); 



     orders.add(new Order(nome, data, livro, telefone, situacao, quantidade, 
      obs)); 

     cl.show(renderPanel, MENUVIEW); 

     return; 

     } 
    }); 
    btnCadastrar.setBounds(424, 429, 89, 33); 
    add(btnCadastrar); 

    JLabel lblNome = new JLabel("Nome:"); 
    lblNome.setBounds(44, 64, 46, 14); 
    add(lblNome); 

    JLabel lblTelefone = new JLabel("Telefone:"); 
    lblTelefone.setBounds(44, 108, 46, 14); 
    add(lblTelefone); 

    JLabel lblLivro = new JLabel("Livro:"); 
    lblLivro.setBounds(44, 150, 46, 14); 
    add(lblLivro); 

    fieldNome = new JTextField(); 
    fieldNome.setBounds(108, 61, 498, 20); 
    add(fieldNome); 
    fieldNome.setColumns(10); 

    fieldTelefone = new JTextField(); 
    fieldTelefone.setBounds(108, 105, 498, 20); 
    add(fieldTelefone); 
    fieldTelefone.setColumns(10); 

    fieldLivro = new JTextField(); 
    fieldLivro.setBounds(108, 147, 498, 20); 
    add(fieldLivro); 
    fieldLivro.setColumns(10); 

    JLabel lblSituao = new JLabel("Situa\u00E7\u00E3o:"); 
    lblSituao.setBounds(44, 186, 46, 14); 
    add(lblSituao); 

    JLabel lblNewLabel = new JLabel("Quantidade:"); 
    lblNewLabel.setBounds(44, 224, 60, 14); 
    add(lblNewLabel); 

    fieldQuantidade = new JTextField(); 
    fieldQuantidade.setBounds(108, 221, 498, 20); 
    add(fieldQuantidade); 
    fieldQuantidade.setColumns(10); 

    JLabel lblObs = new JLabel("Obs:"); 
    lblObs.setBounds(44, 300, 46, 14); 
    add(lblObs); 

    JLabel lblCadastroDeNovo = new JLabel("Cadastro de Novo Pedido"); 
    lblCadastroDeNovo.setFont(new Font("Tahoma", Font.PLAIN, 17)); 
    lblCadastroDeNovo.setBounds(253, 21, 190, 20); 
    add(lblCadastroDeNovo); 

    cBSit = new JComboBox(); 
    cBSit.setModel(new DefaultComboBoxModel(new String[] { "A pedir", 
     "Pedido Feito", "Avisado", "ND", "Esgotado", "Fora de Cat\u00E1logo", 
     "N\u00E3o Encontrado", "Lan\u00E7amento Previsto", "Entregue", 
     "Desisdente" })); 
    cBSit.setSelectedIndex(0); 
    cBSit.setBounds(108, 183, 498, 20); 
    add(cBSit); 

    JLabel lblData = new JLabel("Data:"); 
    lblData.setBounds(44, 261, 46, 14); 
    add(lblData); 

    fieldData = new JTextField(); 
    fieldData.setBounds(108, 261, 498, 20); 
    add(fieldData); 
    fieldData.setColumns(10); 

    fieldObs = new JTextArea(); 
    fieldObs.setText("Sem obs;"); 
    fieldObs.setBounds(108, 300, 498, 96); 
    add(fieldObs); 

    } 
} 

最後一個:

package cantodasletras.br.views; 

import java.awt.BorderLayout; 

public class SearchView extends JPanel { 
    private final String MENUVIEW = "The user menu view"; 
    private JTable table; 
    private JTextField textField_1; 

    /** 
    * Create the panel. 
    */ 
    public SearchView(final CardLayout cl, final JPanel renderPanel, 
    final ArrayList<Order> orders) { 
    GridBagLayout gridBagLayout = new GridBagLayout(); 
    gridBagLayout.columnWidths = 
     new int[] { 0, 0, 17, 224, 66, 333, 77, 0, 0, 0, 0, 0, 0, 0, 0 }; 
    gridBagLayout.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0 }; 
    gridBagLayout.columnWeights = 
     new double[] { 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 
      0.0, 0.0, 0.0, Double.MIN_VALUE }; 
    gridBagLayout.rowWeights = 
     new double[] { 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, Double.MIN_VALUE }; 
    setLayout(gridBagLayout); 

    JLabel lblBuscarCadastro = new JLabel("Buscar Cadastro"); 
    lblBuscarCadastro.setFont(new Font("Tahoma", Font.PLAIN, 17)); 
    GridBagConstraints gbc_lblBuscarCadastro = new GridBagConstraints(); 
    gbc_lblBuscarCadastro.insets = new Insets(0, 0, 5, 5); 
    gbc_lblBuscarCadastro.gridx = 5; 
    gbc_lblBuscarCadastro.gridy = 0; 
    add(lblBuscarCadastro, gbc_lblBuscarCadastro); 

    JLabel lblFiltro = new JLabel("Filtro:"); 
    GridBagConstraints gbc_lblFiltro = new GridBagConstraints(); 
    gbc_lblFiltro.anchor = GridBagConstraints.SOUTH; 
    gbc_lblFiltro.insets = new Insets(0, 0, 5, 5); 
    gbc_lblFiltro.gridx = 3; 
    gbc_lblFiltro.gridy = 1; 
    add(lblFiltro, gbc_lblFiltro); 

    JComboBox comboBox = new JComboBox(); 
    comboBox.setModel(new DefaultComboBoxModel(new String[] { "Nome", "Livro", 
     "A pedir", "Pedido Feito", "Avisado", "ND", "Esgotado", 
     "Fora de Cat\u00E1logo", "N\u00E3o Encontrado", 
     "Lan\u00E7amento Previsto", "Entregue", "Cancelado" })); 
    GridBagConstraints gbc_comboBox = new GridBagConstraints(); 
    gbc_comboBox.insets = new Insets(0, 0, 5, 5); 
    gbc_comboBox.gridx = 3; 
    gbc_comboBox.gridy = 2; 
    add(comboBox, gbc_comboBox); 

    textField_1 = new JTextField(); 
    GridBagConstraints gbc_textField_1 = new GridBagConstraints(); 
    gbc_textField_1.insets = new Insets(0, 0, 5, 5); 
    gbc_textField_1.fill = GridBagConstraints.HORIZONTAL; 
    gbc_textField_1.gridx = 5; 
    gbc_textField_1.gridy = 2; 
    add(textField_1, gbc_textField_1); 
    textField_1.setColumns(10); 

    JButton btnProcurar = new JButton("Procurar"); 
    btnProcurar.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     DefaultTableModel dm = (DefaultTableModel) table.getModel(); 
     dm.setRowCount(0); 
     initTable(orders); 
     } 
    }); 
    GridBagConstraints gbc_btnProcurar = new GridBagConstraints(); 
    gbc_btnProcurar.insets = new Insets(0, 0, 5, 5); 
    gbc_btnProcurar.gridx = 7; 
    gbc_btnProcurar.gridy = 2; 
    add(btnProcurar, gbc_btnProcurar); 

    JButton btnVoltar = new JButton("Voltar"); 
    btnVoltar.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     cl.show(renderPanel, MENUVIEW); 

     } 
    }); 
    GridBagConstraints gbc_btnVoltar = new GridBagConstraints(); 
    gbc_btnVoltar.insets = new Insets(0, 0, 5, 5); 
    gbc_btnVoltar.gridx = 9; 
    gbc_btnVoltar.gridy = 2; 
    add(btnVoltar, gbc_btnVoltar); 

    JPanel panel_1 = new JPanel(); 
    GridBagConstraints gbc_panel_1 = new GridBagConstraints(); 
    gbc_panel_1.gridheight = 3; 
    gbc_panel_1.gridwidth = 9; 
    gbc_panel_1.insets = new Insets(0, 0, 5, 5); 
    gbc_panel_1.fill = GridBagConstraints.BOTH; 
    gbc_panel_1.gridx = 3; 
    gbc_panel_1.gridy = 3; 
    add(panel_1, gbc_panel_1); 

    JComboBox combo = new JComboBox(); 
    combo.setModel(new DefaultComboBoxModel(new String[] { "A pedir", 
     "Pedido Feito", "Avisado", "ND", "Esgotado", "Fora de Cat\u00E1logo", 
     "N\u00E3o Encontrado", "Lan\u00E7amento Previsto", "Entregue", 
     "Desisdente" })); 
    combo.setSelectedIndex(0); 

    panel_1.setLayout(new BorderLayout()); 
    table = new JTable(); 
    table 
     .setModel(new DefaultTableModel(new Object[][] {}, 
     new String[] { "Telefone", "Nome", "Data", "Livro", "Quantidade", 
      "Situacao", "Obs" })); 

    table.getColumn(table.getColumnName(5)).setCellEditor(
     new javax.swing.DefaultCellEditor(combo)); 

    table.getModel().addTableModelListener(new TableModelListener() { 

     public void tableChanged(TableModelEvent e) { 

     if (!(table.getModel().getRowCount() > 0)) 
      return; 

     if (e.getType() == TableModelEvent.UPDATE) { 

      int col = e.getColumn(); 
      int row = e.getFirstRow(); 

      String telefone = (String) table.getValueAt(row, 0); 
      String nome = (String) table.getValueAt(row, 1); 
      String data = (String) table.getValueAt(row, 2); 
      String livro = (String) table.getValueAt(row, 3); 
      String quantidade = (String) table.getValueAt(row, 4); 
      String situacao = ((String) table.getValueAt(row, 5)); 
      String obs = (String) table.getValueAt(row, 6); 

      Order nOrd = 
      new Order(nome, data, livro, telefone, situacao, Integer 
       .parseInt(quantidade), obs); 

      if (col == 0 || col == 1) { 
      int result = 
       JOptionPane 
       .showConfirmDialog(
        (Component) null, 
        "Alterar o nome ou telefone de um cadastro irá gerar um novo cadastro. Deseja continuar?", 
        "Alerta!", JOptionPane.OK_CANCEL_OPTION); 

      if (result == 0) { 

       if (!orders.contains(nOrd)) 
       orders.add(nOrd); 

      } 
      return; 
      } 

      for (Order or : orders) { 

      if (or.equals(nOrd)) 
       orders.remove(or); 
      orders.add(nOrd); 

      } 
     } 

     } 
    }); 

    JScrollPane tableContainer = new JScrollPane(table); 

    panel_1.add(tableContainer, BorderLayout.CENTER); 

    } 

    void initTable(ArrayList<Order> orders) { 
    // Initialize table 

    DefaultTableModel dtm = (DefaultTableModel) table.getModel(); 

    for (Order order : orders) { 

     dtm.addRow(new Object[] { order.getTelefone(), order.getNome(), 
      order.getData(), order.getLivro(), order.getQuantidade().toString(), 
      order.getSituacao(), order.getObs() }); 

    } 

    } 
} 
+0

你能分享你的代碼嗎?否則很難幫助你。 – Jonas

+0

做到了,讓我知道你是否需要別的東西。提前致謝。 – LucasA

+0

如果沒有一個小而孤立但完整且可運行的示例,很難調試您的程序。 – Jonas

回答

2

這是很難理解錯誤發生的地方,因爲你沒有提供完整的堆棧跟蹤,而且代碼不會編譯(如發佈)。

然而,用這種方法從列表中刪除元素(SearchView),而迭代是 不正確,可能是異常的原因:

for (Order or : orders) { 
    if (or.equals(nOrd)) 
     orders.remove(or); 
    } 

你應該使用迭代器及其remove()方法。例如:

for (Iterator<Order> iterator = orders.iterator(); iterator.hasNext();) { 
    Order order = iterator.next(); 
    if (order.equals(nOrd)) { 
     iterator.remove(); 
    } 
} 

有關詳細信息,請參閱The Collection Interface。它規定:

Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

Use Iterator instead of the for-each construct when you need to:

Remove the current element. The for-each construct hides the iterator, so you cannot call remove.

+0

答案部分完整。即使我沒有使用你的建議,我也會接受它。你說得對,不過當你說我以錯誤的方式去除元素時,這實際上是問題的原因。我不確定爲什麼Java將此作爲一個併發問題,但它爲我解決了這個問題。感謝您的時間。 – LucasA

+0

@LucasA很高興幫助你! :)不知道你是什麼意思*一個簡單的雙參考*。在上述情況下,由於您正在修改您正在迭代的集合,因此引發'ConcurrentModificationException'。 – tenorsax