【问题标题】:How to embed a (working) Button in a Swing Table in Scala?如何在 Scala 的 Swing Table 中嵌入(工作)按钮?
【发布时间】:2011-12-26 12:22:41
【问题描述】:

我正在尝试使用 Scala/Swing 创建一个表,其中一个列由 Buttons 填充。

我的出发点是来自 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 书中的方法过于简单?)

感谢您的建议!

【问题讨论】:

    标签: swing scala button renderer


    【解决方案1】:

    您可以通过提供自定义表格模型使列不可编辑。但是,您的单元格必须是可编辑的,因为这是编辑组件变为“活动”的唯一方式(重新绘制状态更改、接收鼠标事件)。

    在正常渲染中(使用renderComponent),组件仅用于“标记”它,即表格只是在组件上调用paint。因此,在性能方面,您应该重用每个渲染组件的一个实例,而不是在每次调用中创建一个新的 Label / 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 tutorial 以了解渲染器和编辑器的复杂细节。

    【讨论】:

    • 谢谢!我的表只会有几行,因此多个标签/按钮的性能影响不应该成为问题,但很高兴看到它以这种方式完成。我也来看看教程。干杯!
    • 我认为它应该使用table.peer.setDefaultEditor 而不是覆盖editor
    猜你喜欢
    • 1970-01-01
    • 2011-12-06
    • 2013-10-06
    • 1970-01-01
    • 2020-10-26
    • 2020-08-13
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多