0

I face scala.MatchError: 0 (of class java.lang.Integer) when I try to add new row to table with custom rendered component:

import java.awt.Dimension

import scala.swing.BorderPanel
import scala.swing.Button
import scala.swing.Component
import scala.swing.Panel
import scala.swing.Table
import javax.swing.table.DefaultTableModel
import scala.swing.Label

object MatchErrorInTable {

  def initPanel() : Panel = {
    val tableModel = new DefaultTableModel(Array[Object]("col1", "col2"), 0)
    val panel = new BorderPanel
    class MyRenderer extends Label {
      def prepare(o: String) {
          text = "foo"
      }
    }
    val tcr = new Table.AbstractRenderer[String, MyRenderer](new MyRenderer) {
      def configure(t: Table, sel: Boolean, foc: Boolean, o: String, row: Int, col: Int) = {
        component.prepare(o)
      }
    }
    val table = new Table(0, 2) {
      override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component  = {
        col match {
          case 1 => tcr.componentFor(this, sel, foc, "bar", row, col)
        }
      }
    }
    table.model = tableModel
   val addButton = Button("add") {
      tableModel.addRow(Array[Object]("text", null))
   }

    panel.layout(table) = BorderPanel.Position.Center
    panel.layout(addButton) = BorderPanel.Position.South
    panel
  }

  def main(args: Array[String]) {
    val mainFrame = new MainFrame()
    mainFrame.preferredSize = new Dimension(800, 600)
    mainFrame.contents = initPanel
    mainFrame.visible = true

  }
}

the exception:

Exception in thread "AWT-EventQueue-0" scala.MatchError: 0 (of class java.lang.Integer)
    at com.mm.calendar.MatchErrorInTable$$anon$1.rendererComponent(MatchErrorInTable.scala:29)
    at scala.swing.Table$$anon$2$$anon$10.getTableCellRendererComponent(Table.scala:116)
    at scala.swing.Table$$anon$2$$anon$10.getTableCellRendererComponent(Table.scala:114)
    at javax.swing.JTable.prepareRenderer(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paintCell(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paintCells(Unknown Source)
    at javax.swing.plaf.basic.BasicTableUI.paint(Unknown Source)
    at javax.swing.plaf.ComponentUI.update(Unknown Source)
    at javax.swing.JComponent.paintComponent(Unknown Source) 

How it is possible that I got java.lang.Integer in rendererComponent?

I was mostly basing my solution on:
Idiomatic table cell renderers in Scala

I'm using 2.11.1 version.

Community
  • 1
  • 1

1 Answers1

0

If you add another

      case _ => tcr.componentFor(this, sel, foc, "foo", row, col)

as a fallback in the match in def rendererComponent, it will at least work without an exception.

You have tow columns in your model, and the actual column indices will be zero and one; these get passed to rendererComponent.


To get a full demo:

import swing._
import javax.swing.table.DefaultTableModel

object MatchErrorInTable {

  def initPanel(): Panel = {
    val tableModel = new DefaultTableModel(Array[Object]("col1", "col2"), 0)
    val panel = new BorderPanel
    class MyRenderer extends Label {
      def prepare(o: String) {
        text = o // changed
      }
    }
    val tcr = new Table.AbstractRenderer[String, MyRenderer](new MyRenderer) {
      def configure(t: Table, sel: Boolean, foc: Boolean, o: String, row: Int, col: Int) = {
        component.prepare(o)
      }
    }
    val table = new Table(0, 2) {
      override protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int): Component = {
        col match {
          case 0 => tcr.componentFor(this, sel, foc, tableModel.getValueAt(row, 0).toString, row, col) // changed
          case 1 => tcr.componentFor(this, sel, foc, tableModel.getValueAt(row, 1).toString, row, col) // changed
        }
      }
    }
    table.model = tableModel
    val addButton = Button("add") {
      tableModel.addRow(Array[Object]("text 1", "text 2")) // changed
    }

    panel.layout(table) = BorderPanel.Position.Center
    panel.layout(addButton) = BorderPanel.Position.South
    panel
  }

  def main(args: Array[String]) {
    val mainFrame = new Frame()
    mainFrame.preferredSize = new Dimension(800, 600)
    mainFrame.contents = initPanel()
    mainFrame.visible = true

  }
}

This way the values you add to the model show up in the table. Of course in this snippet the two case statements do not make much sense; in this case the match is not required, as you always use the same renderer component.

Beryllium
  • 12,808
  • 10
  • 56
  • 86
  • 1
    thanks that solve the problem, but the exception seems pretty confusing to me – Mariusz Marciniak Jul 08 '14 at 12:29
  • @MariuszMarciniak `javax.swing.JTable` is already a hell of a confusion. Add the half-baked Scala facade and your confusion is quadrupled :-O – 0__ Jul 08 '14 at 13:05
  • @0__ couldn't agree more, but there are no good GUI frameworks for Scala and this is just supporting tool app – Mariusz Marciniak Jul 08 '14 at 13:35
  • @0__ I agree as well. On top of that, there won't be scala-swing in 2.12, if they do not find a new maintainer. MariuszMarciniak: It *might* go away, that possibly matters to you. – Beryllium Jul 08 '14 at 14:13
  • @Beryllium I wouldn't worry about the future of Scala Swing. I use it _a lot_. As far as I know, there is already community back-up for continuing the development. Although the API is at times incomplete, Scala-Swing is a pretty finished project. Just some components like tree and table suffer from being weakly typed or convoluted. – 0__ Jul 08 '14 at 15:20