2011-12-26 3 views
3

私はScala/Swingを使用してテーブルを作成しようとしています。テーブルの1つにButtonが設定されています。Scalaのスイングテーブルに(作業中の)ボタンを埋め込む方法は?

私の出発点はOdersky著らのbookからSCells spreadsheet exampleであり、特にrendererComponentの使用は、各セルに現れるComponentを制御します。

ボタンが正常に作成されている間、ボタンはクリックできません。ここには合理的に最小限の自己完結型の例があります:

import swing._ 
import swing.event._ 

class TableButtons extends ScrollPane { 
    viewportView = new Table(2,2) { 
    rowHeight = 25 
    override def rendererComponent(isSelected: Boolean, hasFocus: Boolean, 
            row: Int, column: Int): Component = 
     if (column == 0) { 
     new Label("Hello") 
     } else { 
     val b = new Button { text = "Click" } 
     listenTo(b) 
     reactions += { 
      case ButtonClicked(`b`) => println("Clicked") 
     } 
     b 
     } 
    } 
} 

object Main extends SimpleSwingApplication { 
    def top = new MainFrame { 
    title = "Table button test" 
    contents = new TableButtons 
    } 
} 

私はこれを実行すると、2つの列を持つテーブルを取得します。最初のラベルにはラベルが含まれ、2番目のラベルにはボタンが含まれますが、ボタンはクリックできません。

おそらく関連する問題:セル(ボタンを含むものを含む)が編集可能です。編集を無効にする最良の方法は何ですか?

私はthis question(およびthis oneを)見てきましたし、(Table.AbstractRendererを使用して)そこにアプローチし、次の試してみましたが、それも働いていない - とそのバージョンで、ボタンのクリックに反応を配置する場所、それがすべてで明らかに私にはありません。 (このアプローチは時代遅れですか?またはScalaの本からのアプローチが単純すぎるのでしょうか)

ありがとうございました!

答えて

3

カスタムテーブルモデルを提供することで、編集可能でない列を作成することができます。ただし、セルが編集できるのは、編集コンポーネントが「ライブ」(状態の変更を再描画し、マウスイベントを受け取る)する唯一の方法であるためです。

通常のレンダリングでは(renderComponentを使用)、コンポーネントはコンポーネントの 'スタンプ'するためにのみ使用されます。つまり、コンポーネントのpaintが呼び出されます。したがって、パフォーマンス面では、すべての呼び出しで新しいLabel/Buttonを作成する代わりに、各レンダリングコンポーネントの1つのインスタンスを再利用する必要があります。

したがって、editorメソッドをオーバーライドする必要があります。残念なことに、それは普通のjavax.swing.table.TableCellEditorを返すので、普通のjavax.swingに足を踏み入れて、すべてのスカラの良さを失わなければなりません。

以下はほとんど動作します。 :-(

import scala.swing._ 
import scala.swing.event._ 
import javax.swing.{AbstractCellEditor, JTable} 
import javax.swing.table.TableCellEditor 
import java.awt.{Component => AWTComponent} 

class TableButtons extends ScrollPane { 
    private val lb = new Label("") 
    private val b = new Button 

    private val buttonEditor = new AbstractCellEditor with TableCellEditor { 
    listenTo(b) 
    reactions += { 
     case ButtonClicked(`b`) => 
     println("Clicked") 
     fireEditingStopped() 
    } 
    def getCellEditorValue: AnyRef = "what value?" 
           // ouch, we get JTable not scala.swing.Table ... 
    def getTableCellEditorComponent(tab: JTable, value: AnyRef, isSelected: Boolean, 
             row: Int, col: Int): AWTComponent = { 
     b.text = "Click!" 
     b.peer // ouch... gotta go back to AWT 
    } 
    } 

    viewportView = new Table(2, 2) { 
    rowHeight = 25 
    override def rendererComponent(isSelected: Boolean, hasFocus: Boolean, 
            row: Int, column: Int): Component = 
     if (column == 0) { 
     lb.text = "Hello" 
     lb 
     } else { 
     b.text = "Click?" 
     b 
     } 

    override def editor(row: Int, col: Int): TableCellEditor = 
     if (col == 1) buttonEditor else super.editor(row, col) 
    } 
} 

val top = new Frame { 
    title = "Table button test" 
    contents = new TableButtons 
    pack() 
    visible = true 
} 

は、いずれの場合も、複雑な詳細についてOracle JTable tutorialをチェックする理由は分からない - それをクリックすると奇妙に、ボタンが消えますレンダラとエディタの詳細

+0

ありがとうございます!私のテーブルにはいくつかの行しかないので、multipラベルやボタンは問題にならないはずですが、このようにするのはいいことです。私はチュートリアルも見ていきます。乾杯! – gimboland

+0

私は '' editor''の代わりに 'table.peer.setDefaultEditor'を使うべきだと思います。 –

関連する問題