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!
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 callspainton the component. Thus, performance-wise, you should re-use one instance of each rendering component, instead of creating a newLabel/Buttonin every call.So, you need to override the
editormethod. Unfortunately it returns a plainjavax.swing.table.TableCellEditor, and thus you must step down to the plainjavax.swingstuff and loose all the Scala goodness…The following almost works. Strangely, the button disappears when clicking on it — have no idea why 🙁
In any case, check the Oracle JTable tutorial for the intricate details of renderers and editors.