1

我对 SWING 很陌生,经过一些测试后,我决定使用 CardLayout 来编写一个非常简单的程序:我有 3 张卡片(一张用于登录,一张用于添加数据,另一张用于显示)。问题是我有一个在这些卡之间共享的列表(通过了引用),并且可以被不止一张卡修改。出于某种原因,在我玩了一会儿之后,程序在尝试迭代列表时中断,如下面的错误所示:

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

    }

  }
}
4

1 回答 1

2

由于您没有提供完整的堆栈跟踪,并且代码无法编译(如发布的那样),因此很难理解错误发生在哪里。

但是,在迭代时从列表 (in) 中删除元素的方式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();
    }
}

有关详细信息,请参阅集合接口。它指出:

请注意, Iterator.remove 是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改了基础集合,则行为未指定。

需要时使用 Iterator 而不是 for-each 构造:

删除当前元素。for-each 构造隐藏了迭代器,因此您不能调用 remove。

于 2013-01-25T02:06:25.210 回答