문제

나는 전통적인 자바를 사용하고있었습니다 TableCellRenderer 렌더러를 제공하기위한 접근 방식 scala.swing.Table 테이블에서 렌더러를 선언하는 곳 TableColumnModel. 이에 대한 코드는 다음과 같습니다.

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

불행히도 이것은 메모리 누출이있는 것으로 보입니다. 아마도 테이블의 모든 셀에 대한 새로운 구성 요소 인스턴스 (~ 30k 행). 확실히 내 스칼라 테이블을 a로 교체 할 때 JTable (정확히 동일하게 사용합니다 그리고 데이터 모델) 내 메모리 누출이 사라집니다.

그러므로 내 질문은 사람들이 rendererComponent 자신의 셀 렌더러가 있다고 가정하는 방법?

도움이 되었습니까?

해결책

스칼라 테이블 셀 렌더러를 사용하는 관용적 방법은 사용하는 것입니다. Table.AbstractRenderer (직접 구현하는 경우) 또는 하위 클래스 중 하나 :

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

이 경우 prepare 자신의 렌더러 클래스에서 정의하는 메소드입니다.

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

그런 다음이를 재정의하여 사용합니다 rendererComponent 메소드 켜짐 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에는 자체 구현이 제공됩니다 AbstractRenderer, 즉 LabelRenderer 인스턴스를 변환하는 인수로 기능을 취합니다. myobj a Tuple2 a로 구성됩니다 String 그리고 Icon, 해당 레이블이 표시되도록 :

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

다른 팁

당신의 예제에 감사드립니다. oxbow_lakes!

IMHO이 스칼라는 테이블 렌더링이 얻을 수있는 것처럼 추악 해졌습니다. 가능한 한 많이 숨기려고 ...

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
}

Like 사용 (적어도 "구성"은 사라졌습니다 ...)

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
  }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top