我有一个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错误。
答案 0 :(得分:0)
索引大于或等于5的单元格返回ArrayIndexOutOfBounds错误。
因为您创建了仅5行数据的“ MyTableModel”。如果模型中存在行/列,则只能更改数据。
为什么要使用Swing教程中的“ MyTableModel”作为TableModel?
此外,为什么每次生成“ tableChanged”事件时都要创建一个新的“ MyTableModel”?这意味着您将丢失以前的更改。
我建议如果您尝试将数据从一个表复制到另一个表,那么您需要创建一个DefaultTableModel
,其行/列的数量与生成“ tableChanged”的其他TableModel中的行/列的数量相同”事件。
但是在不知道您的实际要求的情况下,我们无法提供适当的解决方案,只能消除错误。
答案 1 :(得分:0)
当执行到达taulumalli.setValueAt(data, rivi, sarake);
内的行tableChanged()
时,将有2个表模型。
第一个表模型由行table = new JTable(ulkoinen, sarakenimet);
创建。该模型实际上已连接到显示的表。它有70行70列。
在tableChanged()
内部由行MyTableModel taulumalli = new MyTableModel();
创建第二个表模型。即使这是一个表模型,也没有连接到任何表。它有5行5列。
当用户编辑表中的值时,将调用tableChanged()
。在此方法内部,在前两行中,您从第一个表模型获得行索引和列索引(因为显示的表已连接到该表模型)。然后,将第一个表模型的这些行索引和列索引传递给第二个表模型的setValueAt()
。这是不正确的,因为两个表模型具有不同的结构。这会导致错误。