Beanshell Interpreter结合JavaFX:标注无法运行的代码行为何失效?
Beanshell调用JavaFX方法失效的原因分析
我是Beanshell Interpreter新手,之前用instance.method的方式成功调用过方法,但在下面的JavaFX代码里,标有「DOES NOT WORK」的代码行无法运行。下面是有问题的Troubleshoot类代码,以及能正常运行的Example类代码,想知道失效的原因。
存在问题的代码
import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.scene.Group; import javafx.scene.control.Button; import javafx.scene.control.*; import bsh.Interpreter; import javafx.scene.text.Text; public class Troubleshoot extends Application { Group group; Interpreter inter = new Interpreter(); @Override public void start(Stage stage) { group = new Group(); final Scene scene = new Scene(group,1500, 700); scene.setFill(null); Button myButton = new Button("Enter Code"); group.getChildren().add(myButton); myButton.setOnAction(this::buttonClick); EventHandler<ActionEvent> event = new EventHandler<ActionEvent>() { public void handle(ActionEvent e) { try { inter.set("instance", this); inter.set("q", 5.0); //inter.eval("float r = 5.0;"); //WORKS inter.eval("float r = instance.twice(q);"); //DOES NOT WORK Object qq = inter.get("r"); String sq = qq.toString(); float fq = Float.parseFloat(sq); Text v = new Text("r: " + fq); v.setX(700); v.setY(400); group.getChildren().add(v); } catch(Exception f){ Text u = new Text("You didn't assign the variables to a float."); u.setX(700); u.setY(100); } } }; myButton.setOnAction(event); stage.setScene(scene); stage.show(); } private void buttonClick(ActionEvent event) { } public static void main(String[] args) { launch(args); } public float twice(float x) { return 2 * x; } }
可正常运行的代码
import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.geometry.Insets; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.stage.Stage; import bsh.Interpreter; public class Example extends Application { private int count = 0; private Label myLabel = new Label("0"); @Override public void start(Stage stage) { Button myButton = new Button("Count"); GridPane pane = new GridPane(); pane.setPadding(new Insets(10, 10, 10, 10)); pane.setMinSize(300, 300); pane.setVgap(10); pane.setHgap(10); //set an action on the button using method reference myButton.setOnAction(this::buttonClick); // Add the button and label into the pane pane.add(myLabel, 1, 0); pane.add(myButton, 0, 0); // JavaFX must have a Scene (window content) inside a Stage (window) Scene scene = new Scene(pane, 300,100); stage.setTitle("JavaFX Example"); stage.setScene(scene); Interpreter i = new Interpreter(); try{ i.set("instance", this); i.set("y", 7.0f); i.eval("count = instance.twice(y);"); myLabel.setText(i.get("count").toString()); } catch (Exception e){System.out.println("Test");} // Show the Stage (window) stage.show(); } private void buttonClick(ActionEvent event) { } public float twice(float f) {return f*2;} }
问题原因及解决办法
核心问题出在匿名内部类中的this指向错误:
- 在
Example类里,i.set("instance", this);中的this指向Example类的实例,也就是包含twice方法的对象,所以Beanshell能正确找到并调用该方法。 - 但在
Troubleshoot类的匿名EventHandler内部,this指向的是这个匿名内部类的实例(EventHandler对象),而不是Troubleshoot类的实例。这个匿名类并没有twice方法,因此Beanshell执行时会找不到方法,抛出异常并进入catch块。
修复步骤
- 修正
this的指向:把inter.set("instance", this);改为inter.set("instance", Troubleshoot.this);,这样就能正确引用到拥有twice方法的Troubleshoot类实例。 - 统一参数类型:将
inter.set("q", 5.0);改为inter.set("q", 5.0f);,避免double转float的潜在类型问题。 - 添加异常日志:在catch块中加入
f.printStackTrace();,便于查看具体的异常信息,帮助调试。
内容的提问来源于stack exchange,提问作者Craig Sapp
相关产品推荐
相关产品推荐

