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

FXML从控制器读取变量时触发IllegalAccessException异常

问题:使用控制器变量设置Pane尺寸时抛出IllegalAccessException异常

尝试用控制器中的变量设置Pane的尺寸,却一直抛出以下异常:

java.lang.IllegalAccessException: class javafx.fxml.FXMLLoader$ValueElement (in module javafx.fxml) cannot access a member of class blub.Blub with modifiers "private"

编辑说明

已制作最小可复现示例,并且根据建议做了调整,但仍出现相同的IllegalAccessException异常。


startFXMain.java

public class startFXMain extends Application {

    private static MRE myApp;

    public static void main(String[] args) {
        try {
            myApp = MRE.getInstance(args);
            Application.launch(args);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        myApp.start(primaryStage);
    }
}

MRE.java

public class MRE extends Application {
    private static MRE instance = null;

    @Override
    public void start(Stage startStage) throws Exception {
        try {
            new MREGUI(startStage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static MRE getInstance(String[] args) {
        if (Objects.nonNull(instance))
            return instance;
        else synchronized (MRE.class) {
            if (Objects.isNull(instance))
                instance = new MRE();
            return instance;
        }
    }

    public static MRE getInstance() { return instance; }

    private MRE() {
    }
}

MREGUI.java

public class MREGUI extends Application {
    private GraphicsDevice  gd              = GraphicsEnvironment.getLocalGraphicsEnvironment()
            .getDefaultScreenDevice();
    public int              iScreenWidth    = gd.getDisplayMode().getWidth();
    public int              iScreenHeight   = gd.getDisplayMode().getHeight();
    private Scene           scMainScene;
    private Pane            pMainPane;

    @Override
    public void start(Stage stgMainStage) throws Exception {
        this.initStage(stgMainStage);
        this.initStartPane();
        this.initStartScene(this.pMainPane);
        stgMainStage.setScene(this.scMainScene);
        stgMainStage.show();
    }

    private void initStage(Stage s) {
        s.setX(0);
        s.setY(0);
        s.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent e) {
                Platform.exit();
                System.exit(0);
            }
        });
    }

    private void initStartPane() {
        FXMLLoader loader = new FXMLLoader();
        try {
            URL xmlUrl = new File(System.getProperty("user.dir") + "\\src\\startwindow.fxml").toURI().toURL();
            loader.setLocation(xmlUrl);
            pMainPane = loader.load();
            loader.setController(this);
        } catch (MalformedURLException err) {
            err.printStackTrace();
        } catch (IOException err) {
            err.printStackTrace();
        }
    }

    private void initStartScene(Pane rootPane) {
        scMainScene = new Scene(rootPane, iScreenHeight, iScreenWidth);
    }

    public MREGUI(Stage stgMainStage) {
        try {
            this.start(stgMainStage);
        } catch (Exception err) {
            err.printStackTrace();
        }
    }

    private MREGUI() {
    }

    @FXML
    public int getIScreenWidth() { return this.iScreenWidth; }

    @FXML
    public int getIScreenHeight() { return this.iScreenHeight; }

}

startwindow.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.Pane?>

<Pane layoutX="0" layoutY="0" minHeight="640" minWidth="480" prefHeight="${iScreenHeight}" prefWidth="${iScreenWidth}"
        xmlns:fx="http://javafx.com/fxml" fx:controller="MREGUI">
    <style>
     -fx-background-color: blue;
    </style>    
</Pane>

解决方案

1. 修正FXMLLoader控制器设置顺序

当前代码先调用loader.load()再设置控制器,这会导致FXMLLoader读取FXML中的fx:controller属性创建新实例,后续设置的控制器无法生效,进而引发访问权限异常。

正确顺序是先设置控制器,再加载FXML:

private void initStartPane() {
    FXMLLoader loader = new FXMLLoader();
    try {
        URL xmlUrl = new File(System.getProperty("user.dir") + "\\src\\startwindow.fxml").toURI().toURL();
        loader.setLocation(xmlUrl);
        loader.setController(this); // 先绑定控制器
        pMainPane = loader.load(); // 再加载FXML文件
    } catch (MalformedURLException err) {
        err.printStackTrace();
    } catch (IOException err) {
        err.printStackTrace();
    }
}

同时删除FXML中的fx:controller="MREGUI"属性,避免重复创建控制器:

<Pane layoutX="0" layoutY="0" minHeight="640" minWidth="480" prefHeight="${iScreenHeight}" prefWidth="${iScreenWidth}"
        xmlns:fx="http://javafx.com/fxml">
    <style>
     -fx-background-color: blue;
    </style>    
</Pane>

2. 移除MREGUI的Application继承

MREGUI不需要继承Application,启动逻辑已在startFXMain和MRE中处理,继承会导致生命周期冲突:

// 去掉extends Application
public class MREGUI {
    private GraphicsDevice  gd              = GraphicsEnvironment.getLocalGraphicsEnvironment()
            .getDefaultScreenDevice();
    public int              iScreenWidth    = gd.getDisplayMode().getWidth();
    public int              iScreenHeight   = gd.getDisplayMode().getHeight();
    private Scene           scMainScene;
    private Pane            pMainPane;

    // 原start方法改名,去掉@Override注解
    public void initAndShowStage(Stage stgMainStage) throws Exception {
        this.initStage(stgMainStage);
        this.initStartPane();
        this.initStartScene(this.pMainPane);
        stgMainStage.setScene(this.scMainScene);
        stgMainStage.show();
    }

    private void initStage(Stage s) {
        s.setX(0);
        s.setY(0);
        s.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(WindowEvent e) {
                Platform.exit();
                System.exit(0);
            }
        });
    }

    // 其余代码保持不变...
}

然后修改MREGUI的构造函数:

public MREGUI(Stage stgMainStage) {
    try {
        this.initAndShowStage(stgMainStage);
    } catch (Exception err) {
        err.printStackTrace();
    }
}

3. 优化文件路径兼容性

使用跨平台的路径构建方式替代硬编码的Windows分隔符:

Path fxmlPath = Paths.get(System.getProperty("user.dir"), "src", "startwindow.fxml");
URL xmlUrl = fxmlPath.toUri().toURL();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:26:04