2011-12-26 20 views
3

我想用Scala/Swing來創建一個表,其中一列由Button s填充。如何在斯卡拉的Swing Table中嵌入(工作)按鈕?

我的出發點是從Odersky的等人的bookSCells 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 
    } 
} 

當我運行它,我得到兩列的表;第一個包含標籤,第二個包含按鈕,但按鈕不可點擊。

可能相關的問題:單元格(包括包含按鈕的單元格)是可編輯的。禁用編輯的最佳方法是什麼?

我見過this question(和this one),並嘗試(使用Table.AbstractRenderer)以下的方法有但是這也沒有工作 - 這是不是在所有明顯,我在那裏把按鈕點擊反應在該版本。 (這種方法是過時的嗎?還是從Scala書的方法太簡單?)

感謝您的任何建議!

回答

3

您可以通過提供自定義表模型來創建一個可以列的列。但是,您的單元格必須是可編輯的,因爲這是編輯組件變爲「活動」的唯一方式(重繪狀態更改,接收鼠標事件)。

在正常渲染中(使用renderComponent),該組件僅用於「加蓋」它,即該表只調用組件上的paint。因此,在性能方面,您應該重新使用每個渲染組件的一個實例,而不是在每次調用中創建一個新的Label/Button

因此,您需要覆蓋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

謝謝!我的表格只會有幾行,所以性能受到影響標籤/按鈕不應該是一個問題,但很高興看到這樣做。我也會看看這個教程。乾杯! – gimboland 2012-01-03 15:29:53

+0

我認爲它應該使用'table.peer.setDefaultEditor'而不是覆蓋'編輯器'。 – 2017-10-11 03:19:04