Frage

Ich hatte den traditionellen Java TableCellRenderer Ansatz wurde unter Verwendung der Renderer in einem scala.swing.Table für die Bereitstellung, wo ich meine Renderer TableColumnModel steht auf dem Tisch erklären. Der Code für das sah aus wie:

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])
   }
}

Leider scheint dies ein Speicherleck zu haben - vermutlich, weil ich eine neue Komponenteninstanz für jede Zelle in der Tabelle erschaffe (für ~ 30k Zeilen). Sicherlich, wenn ich meinen scala Tisch mit einem JTable ersetzen (mit genau die gleichen Spalte und Daten Modelle) mein Speicherverlust geht weg.

Meine Frage ist also, was für Code tun Menschen verwenden, wenn die rendererComponent Methode überschreibt unter der Annahme einer die eigene Zelle Renderer hat?

War es hilfreich?

Lösung

Die idiomatische Weg Scala Tabellenzelle Renderer zu verwenden, ist Table.AbstractRenderer zu verwenden (wenn Sie Ihre eigene Implementierung) oder einer ihrer Unterklassen:

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)
  }
}

In diesem Fall prepare ist eine Methode, die Sie auf Ihrer eigenen Renderer Klasse definieren würden:

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

Dann wird diese durch Überschreiben der rendererComponent Methode auf Table verwendet:

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 kommt mit seinen eigenen Implementierungen von AbstractRenderer, nämlich LabelRenderer, die eine Funktion als ein Argument nimmt, eine Instanz von Umwandeln MyObj zu einem Tuple2 bestehend aus einem String und einem Icon, für das Etikett zu Anzeige :

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

Andere Tipps

Dank einer Tonne für Ihr Beispiel oxbow_lakes!

IMHO dieses scala-Ding hat so hässlich wie Tisch-Rendering werden kann möglicherweise bekommen. Der Versuch, es so weit wie möglich zu verbergen ...

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
}

Mit wie (zumindest die "konfiguriert" ist weg ...)

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
  }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top