Here is the code:
package scalafx.ensemble.example.charts
import javafx.scene.chart.PieChart.Data
import scala.util.Random
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
import scalafx.scene.chart.PieChart
import scalafx.scene.input.MouseEvent
object BasicPie extends JFXApp {
// data level 1
val pieChartDataBuffer: ObservableBuffer[Data] = ObservableBuffer(
PieChart.Data("A", 20),
PieChart.Data("B", 30),
PieChart.Data("C", 10),
PieChart.Data("D", 40)
)
pieChartDataBuffer.foreach(
(data: Data) => data.node().onMouseClicked = {
(_: MouseEvent) => pieChart.data = pieChartDataSubBuffer(data.name())
}
)
val pieChart = new PieChart {
data = pieChartDataBuffer
title = "DrillDown Pie Chart"
}
// data level 2
val pieChartDataSubBuffer: Map[String, ObservableBuffer[Data]] = _
Array("A", "B", "C", "D").foreach(
(letter: String) => {
val subData: ObservableBuffer[Data] = _
(1 to 10).foreach(
i => {
val subName = letter + "-" + i
subData.add(PieChart.Data(subName, Random.nextInt(100)))
}
)
pieChartDataSubBuffer.updated(letter, subData)
}
)
pieChartDataSubBuffer.foreach(
(nameDataBufferTuple) => {
nameDataBufferTuple._2.foreach(
(data: Data) => {
data.node().onMouseClicked = {
(_: MouseEvent) => pieChart.data = pieChartDataBuffer
}
}
)
}
)
// set listener for one data node
def drillDownData = (pieData: Data, pie: PieChart) => {
pieData.node().onMouseClicked = (_: MouseEvent) => pie.data = pieChartDataSubBuffer(pieData.name())
}
stage = new JFXApp.PrimaryStage {
title = "Drilldown Pie Chart Example"
scene = new Scene {
root = pieChart
}
}
}
One would expect subData
to be initialized with null
, but instead of that I get an error: Unbound placeholder parameter
. Why?
You cannot create an uninitialized val
, because you can never assign anything useful to it afterwards.
Say you make that explicit:
val subData: ObservableBuffer[Data] = null
subData = ObservableBuffer.empty -> error: reassignment to val!
subData.add(data) -> NullPointerException
You either initialize it as a var
var subData: ObservableBuffer[Data] = _
or (especially in case of mutable collections) as empty buffer
val subData: ObservableBuffer[Data] = ObservableBuffer.empty // comes to mind
Your code would suggest that you would want to do the latter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With