Search code examples
swingscalajtablejcomboboxscala-swing

How to add ComboBox as a cell editor in scala.swing.Table?


I'm trying to add ComboBox as a Column Cell Editor for each cell in a second column in Scala Swing application and struggle to do. Following code shows what I have tried so far, please help me to change the code to achieve the task.

import swing._
import javax.swing.JComboBox
import javax.swing.table.AbstractTableModel
import javax.swing.DefaultCellEditor

//////////////////////////////////////////////////////////////////////////////////////////////////
class MyModel(var cells: Array[Array[Any]], val columns: Array[Any] ) extends AbstractTableModel {
  def getRowCount(): Int = cells.length

  def getColumnCount(): Int = columns.length

  def getValueAt(row: Int, col: Int): AnyRef = cells(row)(col).asInstanceOf[AnyRef]

  override def getColumnClass(column: Int) = getValueAt(0, column).getClass

  override def isCellEditable(row: Int, column: Int) = if (column == 0) false else true

  override def setValueAt(value: Any, row: Int, col: Int) {
    cells(row)(col) = value
    fireTableCellUpdated(row, col)
  }

  override def getColumnName(column: Int): String = columns(column).toString
}

//////////////////////////////////////////////////////////////////////////////////////////////////
class TestTable extends ScrollPane {
  final val columns: Array[Any] = Array[Any]( "Column1", "Column2" )

  final val Col1Data: Array[Any] = Array[Any]( "Col1_Data",
      "Col2_Data", "Col3_Data", "Col4_Data", "Col5_Data", "Col6_Data"
  )

  var modelarr = Array.ofDim[Any](Col1Data.length, columns.length)

  for (i <- 0 until Col1Data.length) {
    modelarr(i)(0) = Col1Data(i)
    // Have tried to set it to 1/"Value2"
    modelarr(i)(1) = "Value2"
  }

  val table = new Table( modelarr, columns ) {

    val mymodel = new MyModel(modelarr, columns)
    model = mymodel

    val Col1 = peer.getColumnModel.getColumn( 1 )
    val cb = new JComboBox[String](Array("Value1", "Value2", "Value3"))
    Col1.setCellEditor( new DefaultCellEditor( cb ) )
  }

  viewportView = table
}

//////////////////////////////////////////////////////////////////////////////////////////////////
object MyCombo extends SimpleSwingApplication {

  override def main(args: Array[String]) = super.main(args)

  var mytable = new TestTable

  def top = new MainFrame {
    title = "Table Test"
    contents = mytable
  }
}

Update:

Just found similair question: How to embed a (working) Button in a Swing Table in Scala? Will try suggested approach.


Solution

  • Thanks Nickal for hints. My own solution is a modified version of original code and posting only changes here.

    Modified import block:

    import scala.swing._
    import scala.swing.Swing._
    import javax.swing._
    import javax.swing.table.{TableCellEditor, AbstractTableModel}
    import java.awt.{Component => AWTComponent}
    

    Added two traits to be able to mix java classes in new class:

    //////////////////////////////////////////////////////////////////////////////////////////////////
    trait AbstractCellEditorTrait extends AbstractCellEditor
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    trait TableCellEditorTrait extends TableCellEditor
    
    //////////////////////////////////////////////////////////////////////////////////////////////////
    class comboboxEditor(val currentValue: AnyRef) extends AbstractCellEditorTrait with TableCellEditorTrait {
      private val cb  = new ComboBox(Array("Value1", "Value2", "Value3"))
      cb.selection.item = currentValue.toString
    
      def getCellEditorValue: AnyRef = cb.selection.item.asInstanceOf[AnyRef]
    
      def getTableCellEditorComponent(tab: JTable, value: AnyRef, isSelected: Boolean, row: Int, col: Int): AWTComponent = {
        cb.peer.asInstanceOf[AWTComponent]
      }
    }
    

    Modified code wich sets an cell editor in TestTable class (3 lines of code starting with val Col1 = peer.g are replaced with code below):

      override def editor(row: Int, col: Int): TableCellEditor = {
        if (col == 1) 
          new comboboxEditor(mymodel.getValueAt(row, col))
        else 
          super.editor(row, col)
        }