java 基类,为JTable启用撤消支持

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 基类,为JTable启用撤消支持相关的知识,希望对你有一定的参考价值。

/*
 * Copyright © 2005 by Karsten Kroesch.
 */

import java.util.List;
import java.awt.Toolkit;
import java.awt.datatransfer.*;
import java.io.IOException;
import javax.swing.event.UndoableEditListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoableEditSupport;

/**
 *  Base class to enable undo-support for <code>JTable</code>s.
 *
 * Simply inherit your table model from this class and implement the same methods
 * as in <code>AbstractTableModel</code>. The objects held in this table are
 * stored in <code>rowObjects</code>.
 *
 * Since version 2.0 this table model is instrumented for clipboard operations
 * as well. Simply call the <code>cut</code>, <code>copy</code> and <code>paste</code>
 * methods.
 *
 * @author  Karsten Kroesch
 * @version 2.0
 */
public abstract class AbstractUndoTableModel
  extends AbstractTableModel
  implements ClipboardOwner
{

  /**
   * The table data. The accessible fields of each object are stored in
   * this Collection.
   */
  protected List rowObjects;

  /**
   * The clipboard is the place where <code>cut</code>, <code>copy</code>
   * and <code>paste</code> store their information.
   */
  Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

  public int getRowCount() {
    return rowObjects.size();
  }

  /**
   * Returns the number of accessible fields in your "row object".
   */
  public abstract int getColumnCount();

  /**
   * Maps the table model <code>getValueAt</code> to the object's getter method.
   */
  public abstract Object getValueAt(int row, int col);

  /**
   * This is the modified method with posting changes to undo manager.
   * For your own modifications,
   * override <code>updateValueAt(Object value, int row, int col)</code>.
   */
  public final void setValueAt(Object value, int row, int col) {
    undoableEditSupport.postEdit(new CommandEdit(row, col));
    updateValueAt(value, row, col);
  }

  /**
   * Maps the table model <code>getValueAt</code> to the object's setter method.
   * You may <code>fireTableCellUpdated(row, col)</code> after your modifications
   * at the end of your implementation for changes becoming visible instantly.
   */
  protected abstract void updateValueAt(Object value, int row, int col);

  /**
   * By default, all cells are editable.
   * Override this for customized behaviour.
   */
  public boolean isCellEditable(int row, int col) {
    return true;
  }

  /**
   * Inserting a row into the table model before specified row.
   */
  public void insertRow(Object rowObject, int row) {
    undoableEditSupport.postEdit(new CommandInsert(row));
    rowObjects.add(row, rowObject);
    this.fireTableRowsInserted(row, row);
  }

  /**
   * Removing a row from the table model
   */
  public final void removeRow(int row) {
    if (row < 0) {
      // Ignore command
      return;
    }
    else {
      undoableEditSupport.postEdit(new CommandDelete(row));
      rowObjects.remove(row);
      this.fireTableRowsDeleted(row, row);
    }
  }

  /**
   * Notifies this object that it is no longer the owner of
   * the contents of the clipboard.
   *
   * @param clipboard the clipboard that is no longer owned
   * @param contents the contents which this owner had placed on the clipboard
   *
   * @since 2.0
   */
  public void lostOwnership(Clipboard clipboard, Transferable contents) {
    // Intentionally left blank
  }

  /**
   * Moves the <code>rowObject</code> at given position (presumably selected row) to clipboard.
   *
   * @since 2.0
   */
  public void cut(int row) {
    systemClipboard.setContents(getTransferableAt(row), this);
    removeRow(row);
  }

  /**
   * Copies the <code>rowObject</code> at given position (presumably selected row) to clipboard.
   *
   * @since 2.0
   */
  public void copy(int row) {
    systemClipboard.setContents(getTransferableAt(row), this);
  }

  /**
   * Inserts the clipboard's content before given position (presumably selected row) to clipboard.
   *
   * @throws UnsupportedFlavorException Should never happen since the method only succeeds if supported flavor matches.
   * @throws IOException If the data is no longer available in the requested flavor.
   * @since 2.0
   */
  public void paste(int row)
    throws UnsupportedFlavorException, IOException
  {
    Transferable clipboardContent = systemClipboard.getContents(this);
    DataFlavor[] supportedDataFlavors = getTransferableAt(row).getTransferDataFlavors();
    boolean isSupported = false;
    DataFlavor supportedFlavor = null;
    for (int index = 0; index < supportedDataFlavors.length; index++) {
      isSupported = clipboardContent.isDataFlavorSupported(supportedDataFlavors[index]);
      supportedFlavor = isSupported ? supportedDataFlavors[index] : null;
    }

    // Cannot insert
    if (!isSupported) return;

    insertRow(clipboardContent.getTransferData(supportedFlavor), row);
  }

  /**
   * Returns the <code>Transferable</code> object for given row.
   *
   * This implementation returns only the String representation alue of the copied row.
   * Override this to support cut/copy/paste operations for your desired concept classes.
   *
   * @see #TransferableTarget
   */
  public Transferable getTransferableAt(int row) {
    String value = rowObjects.get(row).toString();
    return new StringSelection(value);
  }

  //
  // declarations for undo support
  //
  protected UndoableEditSupport undoableEditSupport = new UndoableEditSupport(this);

  public void addUndoableEditListener(UndoableEditListener undoableEditListener) {
    undoableEditSupport.addUndoableEditListener(undoableEditListener);
  }

  public void removeUndoableEditListener(UndoableEditListener undoableEditListener) {
    undoableEditSupport.removeUndoableEditListener(undoableEditListener);
  }

  /**
   *  Returns true, if value is valid for assignment to an element in passed
   *  column. Default version always returns true.
   */
  public boolean isValidColumnValue(Object aValue, int row, int col) {
    return true;
  }

  /**
   * getter Method for rowObjects
   * this Collection.
   */
  public List getRowObjects(){
    return rowObjects;
  }

  //
  // Nested Classes
  //

  /**
   * A command class for setting values in table cells
   */
  public class CommandEdit
    extends AbstractUndoableEdit {
    Object value, savedValue;
    int row, col;

    public String getPresentationName() {
      return "setValueAt(" + value + ", " + row + ", " + col + ")";
    }

    public CommandEdit(int row, int col) {
      this.value = getValueAt(row, col);
      this.row = row;
      this.col = col;
    }

    public void redo() throws CannotRedoException {
      super.redo();
      if (savedValue == null) {
        // Should never get here, as super() doesn't permit redoing
        throw new CannotRedoException();
      }
      else {
        updateValueAt(savedValue, row, col);
        savedValue = null;
      }
    }

    public void undo() throws CannotUndoException {
      super.undo();
      savedValue = getValueAt(row, col); // for redo operations
      updateValueAt(value, row, col);
    }
  }

  /**
   * A command class for inserting rows
   */
  public class CommandInsert
    extends AbstractUndoableEdit {
    Object savedRowObject;
    int row;

    public CommandInsert(int row) {
      this.row = row;
    }

    public String getPresentationName() {
      return "Inserted row " + row;
    }

    public void redo() throws CannotRedoException {
      super.redo();
      rowObjects.add(row, savedRowObject);
      fireTableRowsInserted(row, row);
    }

    public void undo() throws CannotUndoException {
      super.undo();
      savedRowObject = rowObjects.get(row);
      rowObjects.remove(row);
      fireTableRowsDeleted(row, row);
    }
  }

  /**
   * A command class for deleting rows
   */
  public class CommandDelete extends AbstractUndoableEdit {
    Object savedRowObject;
    int row;

    public CommandDelete(int row) {
      if (row < 0) {
        System.out.println("could not delete row " + row);
      }
      else {
        savedRowObject = rowObjects.get(row);
        this.row = row;
      }
    }

    public String getPresentationName() {
      return "Deleted row " + row;
    }

    public void redo() throws CannotRedoException {
      if (row < 0) {
        System.out.println("could not redo row " + row);
      }
      else {
        super.redo();
        rowObjects.remove(row);
        fireTableRowsDeleted(row, row);
      }
    }

    public void undo() throws CannotUndoException {
      if (row < 0) {
        System.out.println("could not undo row " + row);
      }
      else {
        super.undo();
        rowObjects.add(row, savedRowObject);
        fireTableRowsInserted(row, row);
      }
    }
  }
}

以上是关于java 基类,为JTable启用撤消支持的主要内容,如果未能解决你的问题,请参考以下文章

撤消/重做菜单项从不启用

如果使用 jtable 事件满足某个条件,则启用 jquery-jtable 隐藏字段

在jquery jtable中启用/禁用“添加新”按钮

多个窗口的核心数据和单独的撤消管理器?

java中如何把JTable设置为不可编辑

java swing JTable显示问题