Pregunta

Yo había estado utilizando el enfoque tradicional TableCellRenderer Java para proporcionar los procesadores en un scala.swing.Table donde declaro mis extracción de grasas en TableColumnModel de la tabla. El código para esta parecía:

val myTable = new Table {
  lazy val tcm = initColumnModel
  peer.setColumnModel(tcm)

  override 
  protected def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int) = {
    //GET THE VALUE FROM THE TableModel
    val value = model.getValueAt(
                        peer.convertRowIndexToModel(row), 
                        peer.convertColumnIndexToModel(col))
    //GET THE RENDERER FROM THE ColumnModel
    val renderer = tcm.getColumn(col).getCellRenderer
    //WRAP IN A COMPONENT
    Component.wrap(renderer.getTableCellRendererComponent(
                        peer, 
                        value, 
                        sel, 
                        foc, 
                        row, 
                        col).asInstanceOf[JComponent])
   }
}

Desafortunadamente esto parece tener una pérdida de memoria - presumiblemente porque estoy creando una nueva instancia de componente para cada celda de la tabla (por filas ~ 30k). Ciertamente, cuando sustituyo mi mesa Scala con un JTable (usando exactamente los mismos columna y datos modelos) mi pérdida de memoria desaparece.

Mi pregunta es, por lo tanto, qué tipo de código de hacer la gente usa cuando reemplazando el método rendererComponent suponiendo que uno tiene los propios procesadores de celdas?

¿Fue útil?

Solución

La forma idiomática de la utilización de procesadores de celdas Scala tabla es utilizar Table.AbstractRenderer (si la implementación de su propia) o una de sus subclases:

val tcr = new Table.AbstractRenderer[MyObj, MyRenderer](new MyRenderer) {
  def configure(t: Table, sel: Boolean, foc: Boolean, o: MyObj, row: Int, col: Int) = {
    //component variable is bound to your renderer
    component.prepare(o)
  }
}

En este caso prepare es un método que se definiría en su propia clase de procesador:

class MyRenderer extends Label {
  def prepare(o: MyObj) {
      text = o.toString //or whatever
  }
}

A continuación, esto se utiliza reemplazando el método rendererComponent en Table:

val t = new Table {
  override def rendererComponent(sel: Boolean, foc: Boolean, row: Int, col: Int) = {
     //FIND VALUE
     val v = model.getValueAt(
                       peer.convertRowIndexToModel(row), 
                       peer.convertColumnIndexToModel(row))
     col match {
       case 0 => tcr.componentFor(this, sel, foc, v, row, col)
     }
  }
}

Scala viene con sus propias implementaciones de AbstractRenderer, a saber LabelRenderer que tiene una función como un argumento, la conversión de una instancia de MyObj a un Tuple2 que consiste en un String y un Icon, para que la etiqueta que se vea :

val ltcr = new LabelRenderer[MyObj] ( (o: MyObj) => (null, o.toString)  )

Otros consejos

Muchísimas gracias por tu ejemplo oxbow_lakes!

En mi humilde opinión esta scala-cosa ha quedado tan feo como tabla-renderizado posiblemente pueda obtener. Tratando de ocultar lo más posible ...

class TableRenderer[A](comp: TableRendererComp[A]) extends Table.AbstractRenderer[A,TableRendererComp[A]](comp) {
  def configure(t: Table, sel: Boolean, foc: Boolean, a: A, row: Int, col: Int): Unit =
    component.render(a, sel, foc)
}

trait TableRendererComp[A] extends Component {
  def render(a: A, sel: Boolean, foc: Boolean): Unit
}

Usando como (al menos la "configurar" se ha ido ...)

val tcr = new TableRenderer[MyObj](new MyRenderer)

class MyRenderer extends Label with TableRendererComp[MyObj] {
  def render(o: MyObj, sel: Boolean, foc: Boolean) {
     text = o.toString //or whatever
  }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top