3

Scala/Swing を使用してテーブルを作成しようとしていますが、その列の 1 つにButtons が入力されています。

私の出発点は、 Odersky et al's bookのSCells スプレッドシートの例であり、特に を使用して各セルの表示を制御します。rendererComponentComponent

残念ながら、これでボタンは正常に作成されますが、ボタンをクリックすることはできません。合理的に最小限の自己完結型の例を次に示します。

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 つの列を持つテーブルが得られます。1 番目にはラベルが含まれ、2 番目にはボタンが含まれますが、ボタンはクリックできません。

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

私はthis question (およびthis one ) を見て、( を使用して) そこでアプローチを試みましたTable.AbstractRendererが、それも機能していません。そのバージョンでボタンのクリックに対する反応をどこに置くべきかはまったくわかりません。(そのアプローチは時代遅れですか? それとも、Scala ブックのアプローチは単純すぎますか?)

アドバイスをありがとう!

4

1 に答える 1

3

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

通常のレンダリング ( を使用renderComponent) では、コンポーネントは「スタンプ」するためだけに使用されます。つまり、テーブルpaintはコンポーネントを呼び出すだけです。したがって、パフォーマンスの観点から、すべての呼び出しで新しいLabel/を作成するのではなく、各レンダリング コンポーネントの 1 つのインスタンスを再利用する必要があります。Button

したがって、editorメソッドをオーバーライドする必要があります。残念ながら、それはプレーンを返すjavax.swing.table.TableCellEditorため、プレーンなものに降りて、javax.swingすべての Scala の利点を失う必要があります...

以下はほぼ動作します。奇妙なことに、ボタンをクリックするとボタンが消えます -- 理由がわかりません :-(

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 チュートリアルを確認してください。

于 2011-12-27T10:18:02.953 に答える