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

Unable to access ScalaFXML controller class members in another class

我有以下代码

@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)

我只想在另一个 class 中使用控制器 class 变量。请帮我访问这些成员变量,谢谢。

我无法测试这是否解决了您的问题,但是 ScalaFXML documentation 表明 @sfxml 宏替换了控制器 class 生成的版本,有效地删除了用户提供的 class 成员。看来这就是您的问题的解释。

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

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)

老实说,这一切看起来相当复杂,并且生成的填充堆栈窗格没有被任何东西使用或添加到场景图中,因此以上内容毫无意义。但是,我希望您能了解这种方法的工作原理,以便您可以在您的应用程序中实现它。

A minimal, complete and verifiable example(包括所有源文件和构建文件)会非常有帮助。