Scala表(JTable)IndexOutOfBoundException由CellEditor的错误索引产生

时间:2014-09-01 20:07:31

标签: swing scala jtable indexoutofboundsexception tablecelleditor

我刚刚遇到一个奇怪的问题,其中IndexOutOfBoundException引发AbstractCellEditor导致Exception尝试索引不存在的行。删除最后一行后出现问题。删除最后一行后,每次可能点击该表都会抛出相同的Exception,直到添加新行。我真的不知道为什么会这样。

在下文中,陈述了scala和产生异常的小Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 4 >= 4 at java.util.Vector.elementAt(Unknown Source) at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source) at javax.swing.JTable.setValueAt(Unknown Source) at javax.swing.JTable.editingStopped(Unknown Source) at javax.swing.AbstractCellEditor.fireEditingStopped(Unknown Source) at javax.swing.AbstractCellEditor.stopCellEditing(Unknown Source) at javax.swing.plaf.basic.BasicTableUI$Handler.mousePressed(Unknown Source) at java.awt.AWTEventMulticaster.mousePressed(Unknown Source) at java.awt.Component.processMouseEvent(Unknown Source) at javax.swing.JComponent.processMouseEvent(Unknown Source) at java.awt.Component.processEvent(Unknown Source) at java.awt.Container.processEvent(Unknown Source) at java.awt.Component.dispatchEventImpl(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source) at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source) at java.awt.Container.dispatchEventImpl(Unknown Source) at java.awt.Window.dispatchEventImpl(Unknown Source) at java.awt.Component.dispatchEvent(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$400(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.awt.EventQueue$3.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.awt.EventQueue$4.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source) 示例:

package test.TableTest

import scala.swing.BorderPanel
import scala.swing.BorderPanel.Position.Center
import scala.swing.MainFrame
import scala.swing.ScrollPane
import java.awt.BorderLayout
import java.awt.Dimension
import scala.swing.GridBagPanel
import scala.swing.TextField
import scala.swing.Button
import scala.swing.Table
import java.awt.GridBagConstraints._
import java.awt.Color
import java.awt.Dimension
import javax.swing.table.DefaultTableModel
import scala.collection.mutable.ListBuffer
import scala.swing.Table.AbstractRenderer
import javax.swing.Icon
import javax.swing.ImageIcon
import scala.swing.event.ButtonClicked
import javax.swing.BorderFactory
import javax.swing.AbstractCellEditor
import javax.swing.table.TableCellEditor
import scala.swing.Label
import javax.swing.JTable
import java.awt.{ Component => AWTComponent }
import java.util.EventObject
import scala.swing.SimpleSwingApplication

object TableTest extends SimpleSwingApplication {
  setSystemLookAndFeel()
  def top = new MainFrame {
    val trackingControl = new TrackingControl
    this.title_=("Table IndexOutOfBound-Example")

    val components = new BorderPanel {
      import BorderPanel.Position._
      add(trackingControl, Center)
    }

    this.contents_=(components)
    this.preferredSize = new Dimension(300,600)
    this.pack
  }
  def setSystemLookAndFeel() {
    import javax.swing.UIManager
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName)
  }
}

class TrackingControl extends GridBagPanel {

  val searchField = new TextField {
    preferredSize_=(new Dimension(200, 22))
  }
  val searchButton = new Button {
    text = "GO"
    reactions += {
      case e: ButtonClicked =>
        if (!searchField.text.isEmpty())
          fireAddToQuery(searchField.text)
    }
  }
  val queryTable = new Table {
    private val buttonRenderer = new AbstractRenderer[Any, Label](new Label) {
      override def configure(table: Table, isSelected: Boolean, hasFocus: Boolean, a: Any, row: Int, column: Int) {
        component.text = "Del"
      }
    }

    private val buttonEditor = new AbstractCellEditor with TableCellEditor {
      val label = new Label
      label.text = "Del"

      override def getCellEditorValue: AnyRef = "Del"
      override def getTableCellEditorComponent(tab: JTable, value: AnyRef, isSelected: Boolean,
        row: Int, col: Int): AWTComponent = {
        fireRemoveFromQuery(row)
        label.peer
      }
    }

    model = new DefaultTableModel(Array[Object]("Tag", "Delete"), 0)
    showGrid = false
    peer.getTableHeader().disable()
    peer.getColumnModel().getColumn(1).setMaxWidth(searchButton.preferredSize.width)
    peer.getColumnModel().getColumn(1).setMinWidth(searchButton.preferredSize.width)

    override def rendererComponent(isSelected: Boolean, focused: Boolean, row: Int, column: Int) = {
      column match {
        case 1 => buttonRenderer.componentFor(this, isSelected, hasFocus, null, row, column)
        case _ => super.rendererComponent(isSelected, focused, row, column)
      }
    }

    override def editor(row: Int, column: Int) = {
      column match {
        case 1 => buttonEditor
        case _ => null
      }
    }
  }

  add(searchField, constraints(0, 0, anchor = GridBagPanel.Anchor.NorthWest))
  add(searchButton, constraints(1, 0, anchor = GridBagPanel.Anchor.NorthEast))
  add(queryTable, constraints(0, 1, gridwidth = 2, fill = GridBagPanel.Fill.Both, weighty = 1))

  def fireAddToQuery(tag: String): Unit = {
    queryTable.model.asInstanceOf[DefaultTableModel].addRow(Array[Object](tag))
  }

  def fireRemoveFromQuery(row: Int): Unit = {
    queryTable.model.asInstanceOf[DefaultTableModel].removeRow(row)
  }

  def constraints(x: Int, y: Int,
    gridwidth: Int = 1, gridheight: Int = 1,
    weightx: Double = 0.0, weighty: Double = 0.0,
    fill: GridBagPanel.Fill.Value = GridBagPanel.Fill.None,
    anchor: GridBagPanel.Anchor.Value = GridBagPanel.Anchor.Center): Constraints = {
    val c = new Constraints
    c.gridx = x
    c.gridy = y
    c.gridwidth = gridwidth
    c.gridheight = gridheight
    c.weightx = weightx
    c.weighty = weighty
    c.fill = fill
    c.anchor = anchor
    c
  }
}

代码:

{{1}}

点击" Del"可以删除一行。在第二栏。

你有什么想法导致这个索引错误吗?

1 个答案:

答案 0 :(得分:0)

我弄清楚问题是什么。

   override def getTableCellEditorComponent(tab: JTable, value: AnyRef, isSelected: Boolean,
        row: Int, col: Int): AWTComponent = {
        fireRemoveFromQuery(row)
        label.peer
      }

我在编辑处于活动状态时删除了该行。我必须在删除行之前取消编辑。

这是表格的剪裁工作:

  val queryTable = new Table {
    model = new DefaultTableModel(Array[Object]("Tag", "Delete"), 0)
    showGrid = false
    peer.getTableHeader().disable()
    peer.getColumnModel().getColumn(1).setMaxWidth(searchButton.preferredSize.width)
    peer.getColumnModel().getColumn(1).setMinWidth(searchButton.preferredSize.width)

    val buttonEditor = new AbstractCellEditor with TableCellEditor {
      var curRow = 0
      val button = new Button
      button.text= "Del"
      button.peer.setBorderPainted(false)
      button.peer.setContentAreaFilled(false)
      button.peer.setOpaque(false)

      listenTo(button)
      reactions += {
        case e: ButtonClicked => {
          cancelCellEditing()
          fireRemoveFromQuery(curRow)
        }
      }

      override def isCellEditable(arg0: EventObject) = true
      override def getCellEditorValue() = "Del"
      override def getTableCellEditorComponent(arg0: JTable, arg1: Any, arg2: Boolean, row: Int, col: Int) = {
        curRow = row
        button.peer
      }
    }
    override def editor(row: Int, column: Int) = {
      column match {
        case 1 => buttonEditor
        case _ => null
      }
    }
  }