I'm playing with ScalaFX because I want to make an encrypted file app but, like the title said, I'm running in to problems. I want to avoid using brackets as I think they are ugly.
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.Scene
import scalafx.scene.control._
import scalafx.scene.layout.BorderPane
import scalafx.event.ActionEvent
import scalafx.scene.layout.HBox
object Start extends JFXApp {
stage = new PrimaryStage {
title = "Eencrypt THAT"
scene = new Scene(600, 300) {
val border = new BorderPane
root = border
val topMenuBar = new MenuBar
border.top = topMenuBar
val topMenuBarList = List()
topMenuBar.menus = topMenuBarList
val menuFileItems = List()
val menuFile = new Menu("File")
menuFile.items = menuFileItems
val menuFileItemNew = new MenuItem("New...")
menuFileItems :+ menuFileItemNew
val menuFileItemSave = new MenuItem("Save")
menuFileItems :+ menuFileItemSave
topMenuBarList :+ menuFile
val menuEditItems = List()
val menuEdit = new Menu("Edit")
menuEdit.items = menuEditItems
val menuEditItemCut = new MenuItem("Cut")
menuEditItems :+ menuEditItemCut
val menuEditItemCopy = new MenuItem("Copy")
menuEditItems :+ menuEditItemCopy
val menuEditItemPaste = new MenuItem("Paste")
menuEditItems :+ menuEditItemPaste
topMenuBarList :+ menuEdit
border.bottom = Label("Lable")
}
}
}
Also is there any way to do some thing like this:
topMenuBar.menus = val topMenuBarList = List()
That way it will be on one line but I'll still have a named list to push too.
One of the issues here is that List()
doesn't work the way you appear to think it does.
Firstly, the :+
operator does indeed append an element to the list (which is a slow operation, since the entire list must be copied each time; you should prefer prepending instead). However, this operator returns a new list containing the appended element, but since you don't store the result, it is thrown away. (Scala List
s are immutable elements, and cannot be modified, so List
operators return new List
instances instead. This is actually highly desirable for Scala's Functional Programming paradigm.)
Secondly, List
s are not observable. Even if you could modify lists by adding elements to it, there would be no way for topMenuBar.menus
, menuFile.items
or menuEdit.items
to know about the additions to their lists. So, all you're doing is copying empty lists to each element.
There are a few alternatives, one which involves initializing List
instances before assigning their contents to the GUI, and the other which uses an ObservableBuffer
instead of a List
. (If using an ObservableBuffer
, you would have to bind it to the associated property, using the ScalaFX <==
operator; there are examples in the ScalaFX demo models. For further background, ObservableBuffer
is the ScalaFX equivalent of JavaFX's ObservableList
.) I'd prefer the former, because observable elements should typically only be used if you need to dynamically modify them during your program's execution.
Here's the first approach, which populates the lists first, then assigns them to the associated GUI element:
import scalafx.application.JFXApp
import scalafx.application.JFXApp.PrimaryStage
import scalafx.scene.Scene
import scalafx.scene.control._
import scalafx.scene.layout.BorderPane
import scalafx.event.ActionEvent
import scalafx.scene.layout.HBox
object Start extends JFXApp {
stage = new PrimaryStage {
title = "Encrypt THAT"
scene = new Scene(600, 300) {
// Create the border pane as the root of the scene.
root = new BorderPane {
// Create the menu bar as the top of the border pane.
top = new MenuBar {
// File menu.
val menuFile = new Menu("File") {
val itemNew = new MenuItem("New...")
val itemSave = new MenuItem("Save")
items = List(itemNew, itemSave)
}
// Edit menu
val menuEdit = new Menu("Edit") {
val itemCut = new MenuItem("Cut")
val itemCopy = new MenuItem("Copy")
val itemPaste = new MenuItem("Paste")
items = List(itemCut, itemCopy, itemPaste)
}
// Add the File and Edit menu to the menu bar.
menus = List(menuFile, menuEdit)
}
// Bottom label.
bottom = Label("Label")
}
}
}
}
BTW, to avoid using braces, you might want to wait for Scala 3 (a.k.a. Dotty), which doesn't need them. In the meantime, your intent might be clearer (and your code less ugly to other Scala programmers) if you put them in. ;-)
Alternatively, provided you populate the lists before assigning them to the GUI elements, you could adapt this code to your braceless style fairly easily.