How to embed a (working) Button in a Swing Table in Scala?

谁说胖子不能爱 提交于 2020-01-02 07:47:08

问题


I'm trying to use Scala/Swing to create a Table, one of whose columns is populated by Buttons.

My starting point is the SCells spreadsheet example from Odersky et al's book, and in particular the use of rendererComponent to control the Component appearing in each cell.

Unfortunately, while this creates a button successfully, the button is not clickable. Here's a reasonably minimal and self-contained example:

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

When I run this, I get a table with two columns; the first contains labels, the second contains buttons, but the buttons aren't clickable.

Possibly related issue: the cells (including the ones containing buttons) are editable. What's the best way to disable editing?

I've seen this question (and this one) and have tried following the approach there (using Table.AbstractRenderer) but that's also not working - and it's not at all obvious to me where to put reactions to button clicks in that version. (Is that approach outdated? Or is the approach from the Scala book too simplisitic?)

Thanks for any advice!


回答1:


You can make a column ineditable by providing a custom table model. However, your cell must be editable, because that is the only way the editing component becomes 'live' (repaints state changes, receives mouse events).

In the normal rendering (using renderComponent), the component is only used to 'stamp' it, i.e. the table just calls paint on the component. Thus, performance-wise, you should re-use one instance of each rendering component, instead of creating a new Label / Button in every call.

So, you need to override the editor method. Unfortunately it returns a plain javax.swing.table.TableCellEditor, and thus you must step down to the plain javax.swing stuff and loose all the Scala goodness...

The following almost works. Strangely, the button disappears when clicking on it -- have no idea why :-(

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
}

In any case, check the Oracle JTable tutorial for the intricate details of renderers and editors.



来源:https://stackoverflow.com/questions/8635737/how-to-embed-a-working-button-in-a-swing-table-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!