gpt4 book ai didi

java - 在 swing 中撤消 JTable

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:24:50 24 4
gpt4 key购买 nike

看看下面显示的代码。当我向表中添加两行并随后尝试执行撤消操作时,我得到一个 java.lang.ArrayIndexOutOfBoundsException: 11 >= 11。谁能告诉我代码有什么问题吗?

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.text.TabExpander;
import javax.swing.undo.*;


public class UndoTable
{
public static void main(String[] args)
{
Object data[][] = {
{"AMZN", "Amazon", 41.28, "BUY"},
{"EBAY", "eBay", 41.57, "BUY"},
{"GOOG", "Google", 388.33, "SELL"},
{"MSFT", "Microsoft", 26.56, "SELL"},
{"NOK", "Nokia Corp", 17.13, "BUY"},
{"ORCL", "Oracle Corp.", 12.52, "BUY"},
{"SUNW", "Sun Microsystems", 3.86, "BUY"},
{"TWX", "Time Warner", 17.66, "SELL"},
{"VOD", "Vodafone Group", 26.02, "SELL"},
{"YHOO", "Yahoo!", 37.69, "BUY"}
};
String columns[] = {"Symbol", "Name", "Price", "Guidance"};

final JvUndoableTableModel tableModel = new JvUndoableTableModel(data, columns);
final JTable table = new JTable(tableModel);
JScrollPane pane = new JScrollPane(table);

JvUndoManager undoManager = new JvUndoManager();
tableModel.addUndoableEditListener(undoManager);

JMenu editMenu = new JMenu("Edit");

Action addrowaction = new AbstractAction("Add Row") {
private static final long serialVersionUID = 1433684360133156145L;


public void actionPerformed(ActionEvent e) {
tableModel.insertRow(table.getRowCount(), new Object[]{"YHOO", "Yahoo!", 37.69, "BUY"});


}
};
editMenu.add(undoManager.getUndoAction());
//editMenu.add(undoManager.getRedoAction());

JMenuBar menuBar = new JMenuBar();
menuBar.add(editMenu);
editMenu.add(addrowaction);


JFrame frame = new JFrame("Undoable JTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(menuBar);
frame.add(pane, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setLocation(200, 300);
frame.setVisible(true);
}
}


class JvUndoableTableModel extends DefaultTableModel
{
public JvUndoableTableModel(Object[][] data, Object[] columnNames)
{
super(data, columnNames);
}


public Class getColumnClass(int column)
{
if (column >= 0 && column < getColumnCount())
return getValueAt(0, column).getClass();

return Object.class;
}



@Override
public void setValueAt(Object value, int row, int column)
{
setValueAt(value, row, column, true);
}


public void setValueAt(Object value, int row, int column, boolean undoable)
{
UndoableEditListener listeners[] = getListeners(UndoableEditListener.class);
if (undoable == false || listeners == null)
{
super.setValueAt(value, row, column);
return;
}


Object oldValue = getValueAt(row, column);
super.setValueAt(value, row, column);

JvCellEdit cellEdit = new JvCellEdit(this, oldValue, value, row, column);
UndoableEditEvent editEvent = new UndoableEditEvent(this, cellEdit);
for (UndoableEditListener listener : listeners)
listener.undoableEditHappened(editEvent);

}

//adding new cell to the table
public void insertRow(int row, Object[] rowData){
insertRow(row, rowData, true);
}

public void insertRow(int row,
Object[] rowData,boolean undoable){
UndoableEditListener listeners[] = getListeners(UndoableEditListener.class);
if (undoable == false || listeners == null)
{
super.insertRow(row, rowData);
return;
}

super.insertRow(row, rowData);
JvCellNew cellNew = new JvCellNew(this, rowData, row);

UndoableEditEvent editEvent = new UndoableEditEvent(this, cellNew);
for (UndoableEditListener listener : listeners)
listener.undoableEditHappened(editEvent);

}


//removing row from the table
public void removeRow(int row){
removeRow(row, true);
}
public void removeRow(int row, boolean undoable){
UndoableEditListener listeners[] = getListeners(UndoableEditListener.class);
if (undoable == false || listeners == null)
{
super.removeRow(row);
return;
}
super.removeRow(row);
JvCellNew cellNew = new JvCellNew(this, row);
UndoableEditEvent editEvent = new UndoableEditEvent(this, cellNew);
for (UndoableEditListener listener : listeners)
listener.undoableEditHappened(editEvent);

}


public void addUndoableEditListener(UndoableEditListener listener)
{
listenerList.add(UndoableEditListener.class, listener);
}
}


class JvCellEdit extends AbstractUndoableEdit
{
protected JvUndoableTableModel tableModel;
protected Object oldValue;
protected Object newValue;
protected int row;
protected int column;


public JvCellEdit(JvUndoableTableModel tableModel, Object oldValue, Object newValue, int row, int column)
{
this.tableModel = tableModel;
this.oldValue = oldValue;
this.newValue = newValue;
this.row = row;
this.column = column;
}


@Override
public String getPresentationName()
{
return "Cell Edit";
}


@Override
public void undo() throws CannotUndoException
{
super.undo();

tableModel.setValueAt(oldValue, row, column, false);
}
}
class JvCellNew extends AbstractUndoableEdit
{
/**
*
*/
private static final long serialVersionUID = 1L;
protected JvUndoableTableModel tableModel;
protected Object[] rowData;
protected int row;

public JvCellNew(JvUndoableTableModel tableModel, Object[] rowData, int row)
{
this.tableModel = tableModel;
this.rowData = rowData;
this.row = row;

}
public JvCellNew(JvUndoableTableModel tableModel, int row)
{
this.tableModel = tableModel;
this.row = row;

}
@Override
public String getPresentationName()
{
return "Cell New";
}
public void undo() throws CannotUndoException
{
super.undo();
tableModel.removeRow(row);

}
}


class JvUndoManager extends UndoManager
{
protected Action undoAction;
// protected Action redoAction;


public JvUndoManager()
{
this.undoAction = new JvUndoAction(this);
synchronizeActions(); // to set initial names
}


public Action getUndoAction()
{
return undoAction;
}



@Override
public boolean addEdit(UndoableEdit anEdit)
{
try
{
return super.addEdit(anEdit);
}
finally
{
synchronizeActions();
}
}


@Override
protected void undoTo(UndoableEdit edit) throws CannotUndoException
{
try
{
super.undoTo(edit);
}
finally
{
synchronizeActions();
}
}


protected void synchronizeActions()
{
undoAction.setEnabled(canUndo());
undoAction.putValue(Action.NAME, getUndoPresentationName());
}
}


class JvUndoAction extends AbstractAction
{
protected final UndoManager manager;


public JvUndoAction(UndoManager manager)
{
this.manager = manager;
}


public void actionPerformed(ActionEvent e)
{
try
{
manager.undo();
}
catch (CannotUndoException ex)
{
ex.printStackTrace();
}
}
}

线程“AWT-EventQueue-0”中的异常 java.lang.ArrayIndexOutOfBoundsException: 11 >= 11 在 java.util.Vector.removeElementAt(未知来源) 在 javax.swing.table.DefaultTableModel.removeRow(未知来源) 在 JvUndoableTableModel.removeRow(UndoTable.java:151) 在 JvUndoableTableModel.removeRow(UndoTable.java:142) 在 JvCellNew.undo(UndoTable.java:233) 在 javax.swing.undo.UndoManager.undoTo(未知来源) 在 JvUndoManager.undoTo(UndoTable.java:279) 在 javax.swing.undo.UndoManager.undo(未知来源) 在 JvUndoAction.actionPerformed(UndoTable.java:311) 在 javax.swing.AbstractButton.fireActionPerformed(未知来源) 在 javax.swing.AbstractButton$Handler.actionPerformed(未知来源) 在 javax.swing.DefaultButtonModel.fireActionPerformed(未知来源) 在 javax.swing.DefaultButtonModel.setPressed(未知来源) 在 javax.swing.AbstractButton.doClick(未知来源) 在 javax.swing.plaf.basic.BasicMenuItemUI.doClick(未知来源) 在 javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(未知来源) 在 java.awt.Component.processMouseEvent(未知来源) 在 javax.swing.JComponent.processMouseEvent(未知来源) 在 java.awt.Component.processEvent(未知来源) 在 java.awt.Container.processEvent(未知来源) 在 java.awt.Component.dispatchEventImpl(未知来源) 在 java.awt.Container.dispatchEventImpl(未知来源) 在 java.awt.Component.dispatchEvent(未知来源) 在 java.awt.LightweightDispatcher.retargetMouseEvent(未知来源) 在 java.awt.LightweightDispatcher.processMouseEvent(未知来源) 在 java.awt.LightweightDispatcher.dispatchEvent(未知来源) 在 java.awt.Container.dispatchEventImpl(未知来源) 在 java.awt.Window.dispatchEventImpl(未知来源) 在 java.awt.Component.dispatchEvent(未知来源) 在 java.awt.EventQueue.dispatchEventImpl(未知来源) 在 java.awt.EventQueue.access$200(未知来源) 在 java.awt.EventQueue$3.run(未知来源) 在 java.awt.EventQueue$3.run(未知来源) 在 java.security.AccessController.doPrivileged( native 方法) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知来源) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知来源) 在 java.awt.EventQueue$4.run(未知来源) 在 java.awt.EventQueue$4.run(未知来源) 在 java.security.AccessController.doPrivileged( native 方法) 在 java.security.ProtectionDomain$1.doIntersectionPrivilege(未知来源) 在 java.awt.EventQueue.dispatchEvent(未知来源) 在 java.awt.EventDispatchThread.pumpOneEventForFilters(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForFilter(未知来源) 在 java.awt.EventDispatchThread.pumpEventsForHierarchy(未知来源) 在 java.awt.EventDispatchThread.pumpEvents(未知来源) 在 java.awt.EventDispatchThread.pumpEvents(未知来源) 在 java.awt.EventDispatchThread.run(未知来源)

最佳答案

问题似乎与执行撤消操作导致再次存储为可撤消操作的操作有关。 (这特别令人困惑,因为删除一行会创建一个新的 JvCellNew,根据名称,它可能表示添加了一个新行)

可以通过指定不能再次撤消已撤消的操作来解决“症状”:

class JvCellNew
{
....
public void undo() throws CannotUndoException
{
super.undo();

// Pass in "false" as the second argument here, to indicate
// that this row removal should NOT cause an undoable edit
tableModel.removeRow(row, false);
}
}

打印一些调试信息时可以更容易地找到类似的东西,例如与

class JvCellNew extends AbstractUndoableEdit
{
....
@Override
public String getPresentationName()
{
return "Cell New "+row; // Print the row number
}

// Provide a useful toString implementation
@Override
public String toString()
{
return getPresentationName();
}
}


class JvUndoManager extends UndoManager
{
....

@Override
public boolean addEdit(UndoableEdit anEdit)
{
try
{
boolean b = super.addEdit(anEdit);

// Print the current state of this manager
System.out.println("After adding "+anEdit);
for (UndoableEdit e : this.edits)
{
System.out.println(e);
}
return b;

}
finally
{
synchronizeActions();
}


}


@Override
protected void undoTo(UndoableEdit edit) throws CannotUndoException
{
try
{
super.undoTo(edit);

// Print the current state of this manager
System.out.println("After undo to "+edit);
for (UndoableEdit e : this.edits)
{
System.out.println(e);
}

}
finally
{
synchronizeActions();
}
}
}

此外,您至少应该考虑区分描述添加行的可撤消编辑和描述删除行的可撤消编辑。

关于java - 在 swing 中撤消 JTable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22960849/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com