无法访问另一个类中的ScalaFXML控制器类成员

时间:2019-03-26 05:16:12

标签: scala scalafx scalafxml

我有以下代码

@sfxml
class Charts(private val predicate_chart:ComboBox[String],
             private val measure_chart : ComboBox[String],
             private val chart_chart : ComboBox[String],
             private val chart_graph : ComboBox[String],
             private val chart_container:Pane) {

       val stackPane = new StackPane()

       def createCharts(): Unit ={    
            new KPie(this).createPie()
       }
}

class KPie(charts:Charts) {
     def createPieUI(result : ResultSet): Unit ={
           val qs: List[QuerySolution] = new IteratorResultSetQuerySolution(result).toList
           val pieChartData = ObservableBuffer(qs.map { v: QuerySolution => PieChart.Data(v.get("s").toString, v.getLiteral("measure").getDouble) })
           val chart = new PieChart(pieChartData)         
           charts.stackPane.getChildren.addAll(chart)
     }
}

在尝试此操作时,出现以下错误

Error: value stackPane is not a member of Charts
    charts.stackPane.getChildren.addAll(chart)

我只想在另一个类中使用控制器类变量。请先帮助我访问那些成员变量。

1 个答案:

答案 0 :(得分:1)

我无法测试这是否可以解决您的问题,但是 ScalaFXML documentation表示@sfxml宏将控制器类替换为生成的版本,该版本有效地删除用户提供的类成员。看来这是您遇到的问题的解释。

文档介绍了一种通过将其他成员放置在扩展了控制器类的trait(或者可能是abstract class)中来提供其他类成员的方法。要访问这些成员,您首先需要通过在getController[Trait]实例上调用Trait(其中FXMLLoader是特征的名称)来获得对控制器的引用。按照这种方法,您的代码将如下所示:

trait ChartsMembers {

  // Note: This stack pane is not apparently used anywhere.
  val stackPane = new StackPane()

  // Note: I added the ResultSet argument which is needed for your example.
  def createCharts(result: ResultSet): Unit = {

    // Note: There was no createPie() member of KPie in your example. I'm assuming that the
    // createPieUI(ResultSet) function was the original intended call. Here's what I did:
    // 1. Renamed createPie to createPieUI.
    // 2. Added the ChartsMembers reference, so that this trait's members are available.
    //
    // Note: The reference to the KPie instance was neither stored nor returned, and so would
    // be garbage collected. Since its charts argument is now redundant, I changed KPie to
    // be an object.
    KPie.createPieUI(this, result)
  }
}

// Note: Charts now extends ChartsMembers.
//
// Note: I have removed the "private val" declarations for the arguments, since they are
// redundant.
@sfxml
class Charts(
  predicate_chart: ComboBox[String],
  measure_chart: ComboBox[String],
  chart_chart: ComboBox[String],
  chart_graph: ComboBox[String],
  chart_container: Pane
) extends ChartsMembers

// Note: This is now an object - see note above.
object KPie {

  // Note: Changed signature - see note above.
  def createPieUI(controller: ChartsMembers, result: ResultSet): Unit = {
    val qs: List[QuerySolution] = new IteratorResultSetQuerySolution(result).toList
    val pieChartData = ObservableBuffer(qs.map { v: QuerySolution => 
      PieChart.Data(v.get("s").toString, v.getLiteral("measure").getDouble)
    })
    val chart = new PieChart(pieChartData)

    // Access the stackPane member on the controller.
    controller.stackPane.getChildren.addAll(chart)
  }
}

要使用以上代码,您首先需要获取一个加载器引用(无论如何都需要),然后使用该引用来调用createCharts函数:

val result = // As required...
val loader = new FXMLLoader(/*Args as required...*/)
val controller = loader.getReference[ChartsMembers]

// Create the charts on the controller.
controller.createCharts(result)

说实话,这一切似乎都令人费解,并且填充的堆栈窗格没有被任何东西使用或未添加到场景图中,因此上述内容毫无意义。但是,希望您能看到这种方法的工作原理,以便可以在应用程序中实现它。

minimal, complete and verifiable example(包括所有源文件和构建文件)将极大地帮助您。