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

FXMLLoader中fx:include的resources属性抛出MissingResourceException问题

问题描述

在FXML文件的<fx:include>标签中使用resources属性加载资源包时抛出MissingResourceException,但手动通过ResourceBundle.getBundle()加载该资源包完全正常。尝试过lang_challenges、wand555/github/io/challengesreworkedgui/lang_challenges等多种路径格式,均无法解决问题。


相关代码

ChallengeApplication.java

package wand555.github.io.challengesreworkedgui;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;

public class ChallengeApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        ResourceBundle.clearCache();
        ResourceBundle bundle = new ResourceBundleWrapper(ResourceBundle.getBundle("wand555/github/io/challengesreworkedgui/lang_challenges"));
        System.out.println(bundle.getString("challenge.name")); // 输出 "abc"
        FXMLLoader loader = new FXMLLoader(ChallengeApplication.class.getResource("overview.fxml"), bundle);
        Parent root = loader.load();
        Scene scene = new Scene(root, 1000, 1000);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }

    // 包装类确保资源包由应用类加载器加载
    private static class ResourceBundleWrapper extends ResourceBundle {

        private final ResourceBundle bundle;

        ResourceBundleWrapper(ResourceBundle bundle) {
            this.bundle = bundle;
        }

        @Override
        protected Object handleGetObject(String key) {
            return bundle.getObject(key);
        }

        @Override
        public Enumeration<String> getKeys() {
            return bundle.getKeys();
        }

        @Override
        public boolean containsKey(String key) {
            return bundle.containsKey(key);
        }

        @Override
        public Locale getLocale() {
            return bundle.getLocale();
        }

        @Override
        public Set<String> keySet() {
            return bundle.keySet();
        }

    }
}

overview.fxml

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

<AnchorPane prefHeight="500.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wand555.github.io.challengesreworkedgui.controllers.OverviewController">
   <children>
      <VBox>
         <children>
            <StackPane alignment="CENTER_LEFT">
               <children>
                  <Button fx:id="exportButton" mnemonicParsing="false" onAction="#onExport" text="Export" />
               </children>
            </StackPane>
            <HBox prefHeight="100.0" prefWidth="200.0" spacing="25.0">
               <children>
                  <fx:include fx:id="challengesOverview" source="challenges/challenges_overview.fxml" resources="lang_challenges" charset="utf-8"/>
                  <Separator orientation="VERTICAL" prefHeight="200.0" />
                  <fx:include source="goals/goal_overview.fxml" />
                  <Separator orientation="VERTICAL" prefHeight="200.0" />
               </children>
            </HBox>
         </children>
      </VBox>
   </children>
</AnchorPane>

资源包文件

lang_challenges.properties:

challenge.name=abc

lang_challenges_de.properties:

challenge.name=abc

错误信息

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:465)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:364)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1082)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: javafx.fxml.LoadException: 
/Users/felixnaumann/Documents/ChallengesReworked/ChallengesReworkedGUI/target/classes/wand555/github/io/challengesreworkedgui/overview.fxml:21

    at javafx.fxml@19/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2707)
    at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2685)
    at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
    at javafx.fxml@19/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2516)
    at challenges.reworked.gui/wand555.github.io.challengesreworkedgui.ChallengeApplication.start(ChallengeApplication.java:22)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
    at javafx.graphics@19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Caused by: java.util.MissingResourceException: Can't find bundle for base name lang_challenges, locale de_DE
    at java.base/java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:2045)
    at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1683)
    at java.base/java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:1575)
    at java.base/java.util.ResourceBundle.getBundle(ResourceBundle.java:1280)
    at javafx.fxml@19/javafx.fxml.FXMLLoader$IncludeElement.processAttribute(FXMLLoader.java:1100)
    at javafx.fxml@19/javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:230)
    at javafx.fxml@19/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:755)
    at javafx.fxml@19/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2808)
    at javafx.fxml@19/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2634)
    ... 9 more
Exception running application wand555.github.io.challengesreworkedgui.ChallengeApplication

解决方案

1. 修正资源包名称格式

FXML的resources属性不支持斜杠分隔的路径,必须使用点分隔的全限定类名格式。把<fx:include>中的resources属性值改成:

resources="wand555.github.io.challengesreworkedgui.lang_challenges"

FXML内部调用ResourceBundle.getBundle()时遵循Java类的全限定名规则,只有点分隔的格式能被正确识别。

2. 复用父FXML的资源包(更推荐)

如果子FXML和父FXML使用同一个资源包,完全不需要在<fx:include>中指定resources属性——子FXML会自动继承父FXML加载时传入的资源包。修改后的代码如下:

<fx:include fx:id="challengesOverview" source="challenges/challenges_overview.fxml" charset="utf-8"/>

这种方式既避免了路径错误,还简化了代码结构。

3. 确认资源文件位置

你的资源包文件已经放在了正确的classpath路径下(target/classes/wand555/github/io/challengesreworkedgui/),手动加载正常也验证了这一点,所以这部分无需调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:40:29