TableView: cells editable on key entry

26 views
Skip to first unread message

Michael Weingran

unread,
Mar 29, 2021, 3:31:15 PM3/29/21
to ScalaFX Users
Hello

I am writing an application in which I am using a TabeView for data entry. Basically I want my TableView to behave like a table in Microsoft Excel (sorry). That is, if you press a key then the cell in the focus is edited immediately (without having to click on it) and if you have entered something in a cell and click on another cell then the entry will not disappeare.
The whole thing is supposed to be a measurement logging app for lathes on a factory floor. 
Unfortunately the documentation for cellFactory is a bit sparse and I'm not very experienced in scalafx yet. I have only done 2 small projects with it and have never used TableView before.

I found in the documentation that for TextFieldTableCell there is a method StartEdit(), but can't figure out how to use it.

For TableView there is also a method edit(row: Int, column: TableColumn[S, _]), but that doesn't do what I want (at least I can't tell what it's doing).

It would be nice if there was a function/method to directly "activate" the input for a cell, so that all text input from keyboard directly ends up in that cell. So far I'm not even sure if this is possible. 
I've thought of using the library java.awt.Robot to send a  '/n' Character to make a cell ready for input, but I really only want to do that as a last resort.

The other point, that you can click into another cell without losing the value is a nice to have, but not so important for me.

Any help would be appreciated very much

Bene Volent

unread,
Mar 30, 2021, 6:25:14 PM3/30/21
to scalaf...@googlegroups.com
These are very generic pointers from my side:
For cellFactory I'd say that the information is there in examples, but at least for me it took some time to fit it with what I am doing. I did not use the TableView portion with cellFactory. Instead I used TreeView with cellFactory to build a directory tree structure from a SQL database. The main breakthrough was to figure out that I needed first to create the structure and data with items and then apply the cellFactory methods on that. 
For further control on your user interaction check controlsfx.org as there is a variety of supplements for enriching the user interaction.

Hope this helps.
Good luck


--
You received this message because you are subscribed to the Google Groups "ScalaFX Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scalafx-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/scalafx-users/27562a61-f90a-4f8b-9dec-98a8a7b912a9n%40googlegroups.com.

Jarek Sacha

unread,
Mar 30, 2021, 9:15:26 PM3/30/21
to scalaf...@googlegroups.com

The ControlFX library mentioned in the previous email has a nice SpreadsheetView component. It may provide functionality you need.


Michael Weingran

unread,
Apr 1, 2021, 10:45:30 AM4/1/21
to ScalaFX Users
Hello

Thanks for the advice. The SpreadsheetView from ControlsFX looks really promissing, so that I gave it a try. I am working on it for more than a day now, but no luck so far. Here is what I've got:
package TestSpreadSheetView

/* Content of build.sbt:
name := "TestSpreadSheetView"
scalaVersion := "2.13.3"
libraryDependencies += "org.scalafx" %% "scalafx" % "15.0.1-R21"
libraryDependencies += "org.controlsfx" % "controlsfx" % "8.40.18"
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
scalacOptions += "-target:jvm-1.8"
*/

import org.controlsfx.control.spreadsheet.{GridBase, SpreadsheetCell, SpreadsheetCellType, SpreadsheetView}
import scalafx.Includes._
import scalafx.application.JFXApp
import scalafx.collections.ObservableBuffer
import scalafx.scene.Scene
import scalafx.scene.layout.StackPane
import scalafx.stage.Stage

object Main extends JFXApp {

val rowCount: Int = 15 //Will be re-calculated after if incorrect.
val columnCount: Int = 10
val grid = new GridBase(rowCount, columnCount)

val spreadSheetView = new SpreadsheetView(grid)

spreadSheetView.setEditable(true)
spreadSheetView.setShowRowHeader(true)
spreadSheetView.setShowColumnHeader(true)

val rows: ObservableBuffer[ObservableBuffer[SpreadsheetCell]] = new ObservableBuffer[ObservableBuffer[SpreadsheetCell]]() //FXCollections.observableArrayList < ObservableList < SpreadsheetCell >> ()
val list = new ObservableBuffer[SpreadsheetCell]() //FXCollections.observableArrayList < SpreadsheetCell > ()

list += SpreadsheetCellType.STRING.createCell(0, 0, 1, 1, "row0-col0")
list += SpreadsheetCellType.STRING.createCell(0, 1, 2, 1, "row0-col1")
list += SpreadsheetCellType.STRING.createCell(0, 2, 1, 1, "row0-col2")
rows += list
list.clear()
list += SpreadsheetCellType.STRING.createCell(1, 0, 1, 1, "row1-col0")
//commenting row1-col1 as row0-col1 has a rowspan of 2
//list += SpreadsheetCellType.STRING.createCell(1, 1, 1, 1, "row1-col1")
list += SpreadsheetCellType.STRING.createCell(1, 2, 1, 1, "row1-col2")
rows += list
list.clear()
list += SpreadsheetCellType.STRING.createCell(2, 0, 1, 1, "row2-col0")
list += SpreadsheetCellType.STRING.createCell(2, 1, 1, 1, "row2-col1")
list += SpreadsheetCellType.STRING.createCell(2, 2, 1, 1, "row2-col2")
rows += list
list.clear()
list += SpreadsheetCellType.STRING.createCell(3, 0, 1, 1, "row3-col0")
list += SpreadsheetCellType.STRING.createCell(3, 1, 1, 1, "row3-col1")
list += SpreadsheetCellType.STRING.createCell(3, 2, 1, 1, "row3-col2")
rows += list

/* Next line will not compile*/
grid.setRows(rows) //rows has the wrong type!!!

val centerPane: StackPane = new StackPane() {
children += spreadSheetView
}

val parentStage: Stage = new JFXApp.PrimaryStage {
title = "Test for SpreadSheetView"
resizable = true
width = 1000
height = 800
scene = new Scene {
root = centerPane
}
}
}

The problem is in the grid for the control. It won't accept an ObservableBuffer and I can't figure out how to import an FXCollections.observableArrayList.

I also checked out the chapter on Unwrapped components on scalafx.org
By the way, the example with a dialog from controlsFX there doesn't work anymore. It seems that Dialog has been deprecated and/or moved to another library.
I'd be willing to translate the example:
to Scala to put it there.
But for someone with the required skills it is probably easier just to do it than teach it to me (I only know scala, not java).

As I said, any help would be appreciated.



Michael Weingran

unread,
Apr 1, 2021, 10:45:30 AM4/1/21
to ScalaFX Users
Update:
I got a SpreadsheetView working. The import was difficult for me.
IntelliJ IDEA keeps complaining "can not resolve symbol" on imports from javafx (import javafx.collections.{FXCollections,ObservableList}), but all compiles and runs fine.
The definitions:

val list = FXCollections.observableArrayList[SpreadsheetCell]()
val rows = FXCollections.observableArrayList[ObservableList[SpreadsheetCell]]()

are very counter-intuitive to me, as list is stored inside of rows later.
But well, its working now and I am going to try to adjust this to my needs.
The line grid.setRows(rows) compiles now with this.

Thanks for the recomondation!

If you have a hint for me how to use this with an obervableBuffer it would still be appreciated.

Thanks!




Jarek schrieb am Mittwoch, 31. März 2021 um 03:15:26 UTC+2:

Jarek

unread,
Apr 1, 2021, 11:22:08 AM4/1/21
to ScalaFX Users

To use ObservableBuffer with list and rows you will need to change signature of the type for rows to ObservableBuffer[jfxc.ObservableList[SpreadsheetCell]]. Note the outer type is ScalaFX ObservableBuffer as before, but the nested type is JavaFX ObservableList. In general ScalaFX cannot deal with automatically converting nested types like that automatically. However, this is the only change needed, the rest can stay the same. You do not need to change type of list it can be ObservableBuffer[SpreadsheetCell]. Here are just the changes:

import javafx.{collections => jfxc}
...
val rows: ObservableBuffer[jfxc.ObservableList[SpreadsheetCell]] = new ObservableBuffer[jfxc.ObservableList[SpreadsheetCell]]()

Michael Weingran

unread,
Apr 1, 2021, 12:07:30 PM4/1/21
to ScalaFX Users
That works.

Thank you very much!

Reply all
Reply to author
Forward
0 new messages