You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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块。

修复步骤

  1. 修正this的指向:把inter.set("instance", this);改为inter.set("instance", Troubleshoot.this);,这样就能正确引用到拥有twice方法的Troubleshoot类实例。
  2. 统一参数类型:将inter.set("q", 5.0);改为inter.set("q", 5.0f);,避免double转float的潜在类型问题。
  3. 添加异常日志:在catch块中加入f.printStackTrace();,便于查看具体的异常信息,帮助调试。

内容的提问来源于stack exchange,提问作者Craig Sapp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 00:25:24