2009-07-28 9 views
9

में इडियोमैटिक टेबल सेल रेंडरर scala.swing.Table में रेंडरर प्रदान करने के लिए पारंपरिक जावा TableCellRenderer दृष्टिकोण का उपयोग कर रहा था, जहां मैं तालिका के 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 पंक्तियों के लिए) बनाने रहा हूँ। निश्चित रूप से जब मैं JTable (उसी कॉलम और डेटा मॉडल) का उपयोग करके अपनी स्कैला तालिका को प्रतिस्थापित करता हूं) मेरी मेमोरी लीक दूर हो जाती है।

इसलिए मेरा प्रश्न यह है कि rendererComponent विधि को ओवरराइड करते समय लोग किस प्रकार के कोड का उपयोग करते हैं, मानते हैं कि किसी के पास स्वयं का सेल रेंडरर है?

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 में एक विधि आप अपने खुद के रेंडरर पर परिभाषित करेगा है:

उत्तर

8

स्काला तालिका सेल दाताओं का उपयोग करने की मुहावरेदार तरह से या उसके उपवर्गों में से एक (अपने खुद को लागू करता है, तो) Table.AbstractRenderer उपयोग करने के लिए है वर्ग:

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

फिर इस Table पर rendererComponent विधि अधिभावी द्वारा किया जाता है:

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

स्काला, अर्थात् AbstractRenderer के अपने स्वयं के कार्यान्वयन के साथ आता है LabelRenderer जो प्रदर्शित करने के लिए उस लेबल के लिए एक तर्क के रूप में एक समारोह लेता है, एक Tuple2 एक String और एक Icon से मिलकर करने के लिए MyObjका एक उदाहरण परिवर्तित:

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

मुझे लगता है कि आप चाहते हैं 'peer.convertColumnIndexToModel (col) 'peer.convertColumnIndexToModel (पंक्ति)' –

+0

के बजाय 'आप 'scala.swing.Table.viewToModelColumn (Int): Int' का भी उपयोग कर सकते हैं। ध्यान दें कि पंक्तियों के लिए समकक्ष रैपर विधि क्यों नहीं है .. –

1

धन्यवाद आपके उदाहरण oxbow_lakes के लिए एक टन!

आईएमएचओ यह स्केल-चीज बदसूरत हो गई है क्योंकि तालिका-प्रतिपादन संभवतः प्राप्त हो सकता है। जितना संभव के रूप में छिपाने की कोशिश कर ...

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 
} 

तरह का उपयोग करना (कम से कम "कॉन्फ़िगर" चला गया है ...)

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

मैंने आपकी टिप्पणी पढ़ी लेकिन पहले इसे नहीं मिला। केवल 'टेबल.ब्रेस्ट्रेंडर' के कई उप-वर्गों के निर्माण के बाद मुझे एहसास हुआ कि मुझे आपके कोड की आवश्यकता क्यों है। मैं जो सुधार जोड़ूंगा वह यह है कि आप शेष 'कॉन्फ़िगरेशन()' पैरामीटर को 'रेंडर (ए, सेल, फोकस, पंक्ति, कॉल)' में पास कर सकते हैं। मुझे अंततः उन सभी की जरूरत थी – Core