Search code examples
scalalinechartscalafx

Scalafx: create lineChart in scala


I am working on a sample of line chart code:

  import scalafx.application.JFXApp
  import scalafx.stage.Stage
  import scalafx.scene.Scene
  import scalafx.scene.chart.{LineChart,NumberAxis, XYChart}
  import scalafx.collections.ObservableBuffer
  import scalafx.scene.chart.XYChart.Series



  object LineChartSample extends JFXApp {

    // Defining the axes
    val xAxis = new NumberAxis()
    xAxis.label = "Number of Month"
    val yAxis = new NumberAxis()

    // Creating the chart
   val lineChart = LineChart(xAxis,yAxis)
     //val lineChart: LineChart[NumberAxis, NumberAxis] = _

    lineChart.title = "Stock Monitoring, 2010"

    // defining a series
    val data = ObservableBuffer(Seq(
      (1, 23),
      (2, 14),
      (3, 15),
      (4, 24),
      (5, 34),
      (6, 36),
      (7, 22),
      (8, 45),
      (9, 43),
      (10, 17),
      (11, 29),
      (12, 25)
    ) map {case (x, y) => XYChart.Data[Number, Number](x, y)} ).delegate

    val series = XYChart.Series[Number,Number]("test",data)




    lineChart.getData.add(series)

    val stg = new Stage {
      title = "Line Chart Sample"
      scene = new Scene(800, 600) {
        root = lineChart
      }
    }
  }

It is failing with error highlighting BELOW line of code on Series

val series = XYChart.Series[Number,Number]("test",data)


Error:(41, 30) overloaded method value apply with alternatives:
  (name: String,data: scalafx.collections.ObservableBuffer[javafx.scene.chart.XYChart.Data[Number,Number]])javafx.scene.chart.XYChart.Series[Number,Number] <and>
  (data: scalafx.collections.ObservableBuffer[javafx.scene.chart.XYChart.Data[Number,Number]])javafx.scene.chart.XYChart.Series[Number,Number]
 cannot be applied to (String, javafx.collections.ObservableList[javafx.scene.chart.XYChart.Data[Number,Number]])
  val series = XYChart.Series[Number,Number]("test",data)

Can someone point me what is wrong with it? I am unable to understand the error properly.


Solution

  • I think the problem here is the use of the .delegate conversion at the end of the ObservableBuffer declaration, which changes data into a JavaFX ObservableList.

    ObservableBuffer (part of ScalaFX) is declared to be equivalent to the JavaFX ObservableList collection class. (I think it was renamed in ScalaFX to avoid confusion with what constitutes a List in Scala.) There is an implicit conversion from ObservableList to ObservableBuffer, but you have not included import scalafx.Includes._ (highly recommended) among your imports. As a result, data doesn't match the expected argument type of XYChart.Series.apply(String, ObservableBuffer), hence the error. By omitting the .delegate call, you simplify your code and do not require the implicit conversion. Alternatively, you could just add that import statement to your code.

    However, if you expect your program to run, you should also assign the stage member of JFXApp to a new PrimaryStage. The following works:

    import scalafx.application.JFXApp
    import scalafx.application.JFXApp.PrimaryStage
    import scalafx.scene.Scene
    import scalafx.scene.chart.{LineChart, NumberAxis, XYChart}
    import scalafx.collections.ObservableBuffer
    
    object LineChartSample
    extends JFXApp {
    
      // Defining the axes
      val xAxis = new NumberAxis()
      xAxis.label = "Number of Month"
      val yAxis = new NumberAxis()
    
      // Creating the chart
      val lineChart = LineChart(xAxis, yAxis)
    
      lineChart.title = "Stock Monitoring, 2010"
    
      // defining a series
      val data = ObservableBuffer(Seq(
        (1, 23),
        (2, 14),
        (3, 15),
        (4, 24),
        (5, 34),
        (6, 36),
        (7, 22),
        (8, 45),
        (9, 43),
        (10, 17),
        (11, 29),
        (12, 25)
      ) map {case (x, y) => XYChart.Data[Number, Number](x, y)})
    
      val series = XYChart.Series[Number, Number]("test", data)
    
      lineChart.getData.add(series)
    
      stage = new PrimaryStage {
        title = "Line Chart Sample"
        scene = new Scene(800, 600) {
          root = lineChart
        }
      }
    }