Cyä*_*gha 5 scala fxml scalafx javafx-8
下面的例子和解释很长,所以这里是我的问题的要点:当使用一个坚持执行字段注入的框架(在真正应该保持私有的字段)时,如何处理scalac的名称 - 私有字段的错误?
我正在使用ScalaFX/JavaFX和FXML在Scala中编写应用程序.当您使用FXML在JavaFX中定义视图时,FXML中定义的对象(例如按钮和文本字段)将通过以下方式注入控制器:
fx:idFXML元素添加属性@FXML注释和字段名称与fx:idFXML中定义的属性值匹配FXMLoader实例化控制器时,它会通过反射自动将带fx:id注释的元素注入到@FXML控制器的匹配注释字段中我不是现场注射的忠实粉丝,但这就是FXML的工作方式.但是,由于编译器在某些情况下执行的字段名称修改,我在Scala中遇到了意外的并发症......
这是一个示例应用程序:
test/TestApp.scala(没什么好玩的,只需要运行这个例子)
package test
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.{Scene, Parent}
import javafx.stage.Stage
object TestApp {
def main(args: Array[String]) {
Application.launch(classOf[TestApp], args: _*)
}
}
class TestApp extends Application {
override def start(primaryStage: Stage): Unit = {
val root: Parent = FXMLLoader.load(getClass.getResource("/test.fxml"))
val scene: Scene = new Scene(root, 200, 200)
primaryStage.setTitle("Test")
primaryStage.setScene(scene)
primaryStage.show()
}
}
Run Code Online (Sandbox Code Playgroud)
test.fxml(视图)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="test.TestController">
<children>
<CheckBox fx:id="testCheckBox" mnemonicParsing="false" text="CheckBox"/>
<Button fx:id="testButton" mnemonicParsing="false" text="Button"/>
</children>
</VBox>
Run Code Online (Sandbox Code Playgroud)
test/TestController.scala(test.fxml视图的控制器)
package test
import javafx.fxml.FXML
import javafx.scene.{control => jfxsc}
import scalafx.Includes._
class TestController {
@FXML private var testCheckBox: jfxsc.CheckBox = _
@FXML private var testButton: jfxsc.Button = _
def initialize(): Unit = {
println(s"testCheckBox=$testCheckBox")
println(s"testButton=$testButton")
testCheckBox.selected.onChange {
testButton.text = "changed"
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行应用程序时,println语句显示testCheckBox正确注入,但testButton为null.如果我点击复选框,就会有预期的,NullPointerException在通话时testButton.text_=.
查看编译的类时,原因很明显:
TestController$$anonfun$initialize$1类,用于testCheckBox.selected.onChange()在initialize()方法中传递给的匿名函数TestController类中,有两个私有字段:( testCheckBox按预期方式)和test$TestController$$testButton(而不仅仅是testButton)和accessor/mutator方法.其中,只有访问者方法test$TestController$$testButton是公开的.很明显,Scala编译器损坏了该testButton字段的名称,因为它必须公开其访问器方法(从中访问它TestController$$anonfun$initialize$1),并且因为字段和accesor/mutator方法应该保持相同的名称.
现在,最后,我的问题是:有没有合理的解决方案来处理这种情况?现在,我所做的是将字段公开:因为编译器不需要改变它们的可见性,所以它不会破坏它们的名字.但是,这些领域真的没有公开的业务.
注意:另一个解决方案是使用scala-fxml库,它完全隐藏了字段注入,但出于其他原因,我宁愿使用bog标准的FXML加载.
这就是我声明注入字段的方式:
@FXML
var popoutButton: Button = _
Run Code Online (Sandbox Code Playgroud)
IOW,离开private,一切正常。如果您来自Java世界,这会觉得有些脏,但是解决方法需要更多的代码。
暗示的控制器fx:include也可以正常工作:
FXML:
<fx:include fx:id="paramTable" source="ParameterTable.fxml" />
Run Code Online (Sandbox Code Playgroud)
Scala:
@FXML
var paramTable: TableView[(ModelParameter, ParameterValue)] = _
@FXML
var paramTableController: ParameterTableController = _
Run Code Online (Sandbox Code Playgroud)