2009-07-28 11 views
9

He estado utilizando el enfoque tradicional Java TableCellRenderer para proporcionar los procesadores en un scala.swing.Table donde declaro mis representadores en TableColumnModel de la tabla. El código para esta parecía:Representadores de células de tabla idiomática en Scala

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 reemplazo mi tabla scala con JTable (usando exactamente la misma columna y data modelos) mi pérdida de memoria desaparece.

Mi pregunta es, por lo tanto, ¿qué tipo de código utilizan las personas cuando se reemplaza el método rendererComponent suponiendo que uno tiene sus propios procesadores de células?

Respuesta

8

La forma idiomática de utilizar Scala procesadores de celdas mesa 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 propio procesador clase:

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

Entonces este 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 de pantalla:

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

Creo que quieres 'peer.convertColumnIndexToModel (col) 'en lugar de' peer.convertColumnIndexToModel (fila) ' –

+0

También puede usar' scala.swing.Table.viewToModelColumn (Int): Int'. Tenga en cuenta por qué no hay un método de envoltura equivalente para las filas. –

1

¡Muchas gracias por su ejemplo oxbow_lakes!

En mi humilde opinión, esta scala-thing se ha vuelto tan fea como la renderización de tablas puede llegar a ser. 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 
    } 
} 
+0

Leí su comentario, pero al principio no lo entendí. Solo después de crear varias sub clases de 'Table.AbstractRenderer' me di cuenta de por qué necesitaba su código. La mejora que agregaría es que también puede pasar los parámetros 'configure()' restantes a 'render (a, sel, foc, row, col)'. Finalmente los necesité a todos – Core

Cuestiones relacionadas