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

完全なスタック トレースを提供していないため、エラーが発生した場所を理解するのが難しく、コードがコンパイルされません (投稿されたとおり)。

ただし、反復中に ( で) リストから要素を削除する方法SearchViewは正しくなく、例外の原因になる可能性があります。

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

iterator とそのremove()メソッドを使用する必要があります。例えば:

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

詳細については、コレクション インターフェイスを参照してください。それは述べています:

Iterator.remove は、反復中にコレクションを変更する唯一の安全な方法であることに注意してください。反復の進行中に基になるコレクションが他の方法で変更された場合、動作は規定されていません。

次のことが必要な場合は、for-each コンストラクトの代わりに Iterator を使用します。

現在の要素を削除します。for-each コンストラクトは反復子を非表示にするため、remove を呼び出すことはできません。

于 2013-01-25T02:06:25.210 に答える