Как исправить ошибку «TableModel.setValueAt ArrayIndexOutOfBoundsException» в Java - PullRequest
0 голосов
/ 09 января 2019

У меня есть приложение JTable. Мне нужно изменить значения ячеек и сохранить данные, но в пределах массива находятся только ячейки с индексом, меньшим или равным 4.

package fi.allu.neliojuuri;

import com.sun.glass.events.KeyEvent;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import javax.swing.event.CellEditorListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class Neliojuuri extends JPanel
    implements ActionListener, ItemListener, TableModelListener {

String newline = "\n";
private JTable table;
private JCheckBox rowCheck;
private JCheckBox columnCheck;
private JCheckBox cellCheck;
private ButtonGroup buttonGroup;
private JTextArea output;

private String[] sarakenimet = new String[70];
private String[] sisakkainen = new String[70];
private Object[][] ulkoinen = new String[71][71];

private DefaultTableModel oletusmalli = null;
private CellEditorListener solumuokkaaja = null;

public Neliojuuri() {
    super();
    setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));        

    for (int i = 0; i < 70; i++) {
            sarakenimet[i] = String.valueOf(i + 1);
        }

        for (int i = 0; i < sisakkainen.length; i++) {
            sisakkainen[i] = String.valueOf(i + 1);
        }

        for (int i = 0; i < ulkoinen.length; i++) {
            ulkoinen[i] = sisakkainen;
        }

    table = new JTable(ulkoinen, sarakenimet);
    table.setPreferredScrollableViewportSize(new Dimension(500, 210));
    table.setFillsViewportHeight(true);
    table.setRowHeight(30);

    TableColumnModel sarakeMalli = table.getColumnModel();
    for (int i = 0; i < 70; i++) {
        sarakeMalli.getColumn(i).setPreferredWidth(75);
    }

    oletusmalli = new javax.swing.table.DefaultTableModel();
    table.setModel(oletusmalli);

    String[] sarakenimet = new String[70];
    for (int i = 0; i < 70; i++) {
        sarakenimet[i] = String.valueOf(i + 1);
    }

    String[] sisakkainen = new String[70];
    for (int i = 0; i < sisakkainen.length; i++) {
        sisakkainen[i] = String.valueOf(i + 1);
    }
    Object[][] ulkoinen = new String[71][71];
    for (int i = 0; i < ulkoinen.length; i++) {
        ulkoinen[i] = sisakkainen;
    }

    oletusmalli.setColumnIdentifiers(sarakenimet);

    for (int count = 0; count < 70; count++){
        oletusmalli.insertRow(count, sisakkainen);
    }

    table.getSelectionModel().addListSelectionListener(new RowListener());
    table.getColumnModel().getSelectionModel().
            addListSelectionListener(new ColumnListener());
    add(new JScrollPane(table, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
        JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

    table.getModel().addTableModelListener(this);

    add(new JLabel("Selection Mode"));
    buttonGroup = new ButtonGroup();
    addRadio("Multiple Interval Selection").setSelected(true);
    addRadio("Single Selection");
    addRadio("Single Interval Selection");

    add(new JLabel("Selection Options"));
    rowCheck = addCheckBox("Row Selection");
    rowCheck.setSelected(true);
    columnCheck = addCheckBox("Column Selection");
    cellCheck = addCheckBox("Cell Selection");
    cellCheck.setEnabled(false);

    output = new JTextArea(5, 40);
    output.setEditable(false);
    output.setFont(new Font("Segoe UI", Font.PLAIN, 20));
    add(new JScrollPane(output));
}

private JCheckBox addCheckBox(String text) {
    JCheckBox checkBox = new JCheckBox(text);
    checkBox.addActionListener(this);
    add(checkBox);
    return checkBox;
}

private JRadioButton addRadio(String text) {
    JRadioButton b = new JRadioButton(text);
    b.addActionListener(this);
    buttonGroup.add(b);
    add(b);
    return b;
}

public void actionPerformed(ActionEvent e) {        
    JFileChooser tiedostovalitsin = new JFileChooser();        

    JMenuItem source = (JMenuItem)(e.getSource());
    if (source.getText() == "Save") {
        int palautusArvo = tiedostovalitsin.showSaveDialog(Neliojuuri.this);

        if (palautusArvo == JFileChooser.APPROVE_OPTION) {
            File tiedosto = tiedostovalitsin.getSelectedFile();
            // Tallenna tiedosto oikeasti
            for (int i = 0; i < oletusmalli.getRowCount(); i++) {
                System.out.println(oletusmalli.getValueAt(1, i).toString());
            }
            System.out.println(tiedosto.getName());
        }
    }

    String command = e.getActionCommand();
    //Cell selection is disabled in Multiple Interval Selection
    //mode. The enabled state of cellCheck is a convenient flag
    //for this status.
    if ("Row Selection" == command) {
        table.setRowSelectionAllowed(rowCheck.isSelected());
        //In MIS mode, column selection allowed must be the
        //opposite of row selection allowed.
        if (!cellCheck.isEnabled()) {
            table.setColumnSelectionAllowed(!rowCheck.isSelected());
        }
    } else if ("Column Selection" == command) {
        table.setColumnSelectionAllowed(columnCheck.isSelected());
        //In MIS mode, row selection allowed must be the
        //opposite of column selection allowed.
        if (!cellCheck.isEnabled()) {
            table.setRowSelectionAllowed(!columnCheck.isSelected());
        }
    } else if ("Cell Selection" == command) {
        table.setCellSelectionEnabled(cellCheck.isSelected());
    } else if ("Multiple Interval Selection" == command) {
        table.setSelectionMode(
                ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        //If cell selection is on, turn it off.
        if (cellCheck.isSelected()) {
            cellCheck.setSelected(false);
            table.setCellSelectionEnabled(false);
        }
        //And don't let it be turned back on.
        cellCheck.setEnabled(false);
    } else if ("Single Interval Selection" == command) {
        table.setSelectionMode(
                ListSelectionModel.SINGLE_INTERVAL_SELECTION);
        //Cell selection is ok in this mode.
        cellCheck.setEnabled(true);
    } else if ("Single Selection" == command) {
        table.setSelectionMode(
                ListSelectionModel.SINGLE_SELECTION);
        //Cell selection is ok in this mode.
        cellCheck.setEnabled(true);
    }

    //Update checkboxes to reflect selection mode side effects.
    rowCheck.setSelected(table.getRowSelectionAllowed());
    columnCheck.setSelected(table.getColumnSelectionAllowed());
    if (cellCheck.isEnabled()) {
        cellCheck.setSelected(table.getCellSelectionEnabled());
    }
}

private void outputSelection() {
    output.append(String.format("Lead: %d, %d. ",
            table.getSelectionModel().getLeadSelectionIndex(),
            table.getColumnModel().getSelectionModel().
                    getLeadSelectionIndex()));
    output.append("Rows:");
    for (int c : table.getSelectedRows()) {
        output.append(String.format(" %d", c));
    }
    output.append(". Columns:");
    for (int c : table.getSelectedColumns()) {
        output.append(String.format(" %d", c));
    }
    output.append(".\n");
}

@Override
public void itemStateChanged(ItemEvent e) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

@Override
public void tableChanged(TableModelEvent e) {
    int rivi = e.getFirstRow();
    int sarake = e.getColumn();
    TableModel malli = (TableModel)e.getSource();
    String sarakeNimi = malli.getColumnName(sarake);
    Object data = malli.getValueAt(rivi, sarake);
    MyTableModel taulumalli = new MyTableModel();
    taulumalli.setValueAt(data, rivi, sarake);
    System.out.println("rivi: " + rivi + " sarake: " + sarake + " data: " + data);
}

private void setValueAt(Object data, int rivi, int sarake) {
    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

private class RowListener implements ListSelectionListener {

    public void valueChanged(ListSelectionEvent event) {
        if (event.getValueIsAdjusting()) {
            return;
        }
        output.append("ROW SELECTION EVENT. ");
        outputSelection();
    }
}

private class ColumnListener implements ListSelectionListener {

    public void valueChanged(ListSelectionEvent event) {
        if (event.getValueIsAdjusting()) {
            return;
        }
        output.append("COLUMN SELECTION EVENT. ");
        outputSelection();
    }
}

class MyTableModel extends AbstractTableModel {

    private String[] columnNames = {"First Name",
        "Last Name",
        "Sport",
        "# of Years",
        "Vegetarian"};
    private Object[][] data = {
        {"Kathy", "Smith",
            "Snowboarding", new Integer(5), new Boolean(false)},
        {"John", "Doe",
            "Rowing", new Integer(3), new Boolean(true)},
        {"Sue", "Black",
            "Knitting", new Integer(2), new Boolean(false)},
        {"Jane", "White",
            "Speed reading", new Integer(20), new Boolean(true)},
        {"Joe", "Brown",
            "Pool", new Integer(10), new Boolean(false)}
    };

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.length;
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    /*
     * JTable uses this method to determine the default renderer/
     * editor for each cell.  If we didn't implement this method,
     * then the last column would contain text ("true"/"false"),
     * rather than a check box.
     */
    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col < 2) {
            return false;
        } else {
            return true;
        }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }

}

public JMenuBar luoValikkoPalkki() {
    JMenuBar valikkopalkki = new JMenuBar();
    JMenu valikko = new JMenu("File");
    valikko.setMnemonic(KeyEvent.VK_F);
    valikko.getAccessibleContext().setAccessibleDescription(
            "File saving menu");
    valikkopalkki.add(valikko);

    JMenuItem valikkoitem = new JMenuItem("Save", KeyEvent.VK_S);
    valikkoitem.setAccelerator(KeyStroke.getKeyStroke(
            java.awt.event.KeyEvent.VK_S, ActionEvent.CTRL_MASK));
    valikkoitem.addActionListener(this);
    valikko.add(valikkoitem);
    return valikkopalkki;
}

/**
 * Create the GUI and show it. For thread safety, this method should be
 * invoked from the event-dispatching thread.
 */
private static void createAndShowGUI() {
    //Disable boldface controls.
    UIManager.put("swing.boldMetal", Boolean.FALSE);

    try {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (Exception e) {
        e.printStackTrace();
    }
    //Create and set up the window.
    JFrame frame = new JFrame("Neliöjuuri");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    Neliojuuri neliojuuri = new Neliojuuri();
    frame.setJMenuBar(neliojuuri.luoValikkoPalkki());

    //Create and set up the content pane.
    Neliojuuri newContentPane = new Neliojuuri();
    newContentPane.setOpaque(true); //content panes must be opaque
    frame.setContentPane(newContentPane);

    //Display the window.
    frame.pack();
    frame.setVisible(true);
}

public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}
}

StackTrace:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 5
at fi.allu.neliojuuri.Neliojuuri$MyTableModel.setValueAt(Neliojuuri.java:356)
at fi.allu.neliojuuri.Neliojuuri.tableChanged(Neliojuuri.java:261)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableCellUpdated(AbstractTableModel.java:275)
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:666)
at javax.swing.JTable.setValueAt(JTable.java:2744)
at javax.swing.JTable.editingStopped(JTable.java:4729)
at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:141)
at javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(DefaultCellEditor.java:368)
at javax.swing.DefaultCellEditor.stopCellEditing(DefaultCellEditor.java:233)
at javax.swing.JTable$GenericEditor.stopCellEditing(JTable.java:5473)
at javax.swing.DefaultCellEditor$EditorDelegate.actionPerformed(DefaultCellEditor.java:385)
at javax.swing.JTextField.fireActionPerformed(JTextField.java:508)
at javax.swing.JTextField.postActionEvent(JTextField.java:721)
at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:836)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1668)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2882)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2929)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2845)
at java.awt.Component.processEvent(Component.java:6316)
at java.awt.Container.processEvent(Container.java:2239)
at java.awt.Component.dispatchEventImpl(Component.java:4889)
at java.awt.Container.dispatchEventImpl(Container.java:2297)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1954)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:835)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1103)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:974)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:800)
at java.awt.Component.dispatchEventImpl(Component.java:4760)
at java.awt.Container.dispatchEventImpl(Container.java:2297)
at java.awt.Window.dispatchEventImpl(Window.java:2746)
at java.awt.Component.dispatchEvent(Component.java:4711)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
at java.awt.EventQueue$4.run(EventQueue.java:733)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82) 

Я ожидаю, что смогу изменить все значения ячеек в таблице, но я могу сделать это только для некоторых из них. Ячейки с индексом, большим или равным 5, возвращают ошибку ArrayIndexOutOfBounds.

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Когда выполнение достигает строки taulumalli.setValueAt(data, rivi, sarake); внутри tableChanged(), существуют две модели таблиц.

Первая табличная модель создается строкой table = new JTable(ulkoinen, sarakenimet);. Эта модель фактически связана с отображаемой таблицей. Имеет 70 строк и 70 столбцов.

Вторая табличная модель создается внутри tableChanged() линией MyTableModel taulumalli = new MyTableModel();. Несмотря на то, что это табличная модель, она не связана ни с одной таблицей. Это имеет 5 строк и 5 столбцов.

Когда пользователь редактирует значение в таблице, вызывается tableChanged(). Внутри этого метода в первых двух строках индекс строки и индекс столбца, которые вы получаете, взяты из первой модели таблицы (поскольку отображаемая таблица связана с этой моделью таблицы). Затем вы передаете эти индекс строки и индекс столбца первой модели таблицы в setValueAt() второй модели таблицы. Что неверно, потому что две модели таблиц имеют разную структуру. Это вызывает ошибку.

0 голосов
/ 09 января 2019

Ячейки с индексом, большим или равным 5, возвращают ошибку ArrayIndexOutOfBounds.

Потому что вы создаете свою «MyTableModel», которая только 5 строк данных. Вы можете изменить данные, только если в модели есть строка / столбец.

Зачем вам использовать "MyTableModel" из учебного пособия по Swing в качестве TableModel?

Кроме того, зачем создавать новый MyTableModel каждый раз, когда генерируется событие tableChanged? Это означает, что вы потеряете предыдущие изменения.

Я бы предложил, если вы пытаетесь скопировать данные из одной таблицы в другую, тогда вам нужно создать DefaultTableModel с тем же числом строк / столбцов, которое существует в другой TableModel, которая сгенерировала событие tableChanged. ,

Но, не зная ваших реальных требований, мы не можем дать правильное решение, только устранить ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...