基于Maven的CodenameOne项目CSS主题切换及.res文件生成咨询
问题
我在基于Maven的CodenameOne项目中切换CSS主题时遇到了困难,操作步骤及问题如下:
- 已通过Steve的博客将项目迁移至Maven,当前使用现有
theme.css; - 项目启动时的主题初始化代码:
try { resources = Resources.openLayered("/MailAngel"); java.util.Hashtable vals = resources.getTheme(resources.getThemeResourceNames()[0]); UIManager.getInstance().setThemeProps(vals); Resources theme = Resources.openLayered( Constants.THEME_LIGHT ); UIManager.getInstance().addThemeProps(theme.getTheme(theme.getThemeResourceNames()[0])); Resources.setGlobalResources(theme); //todo: get the device language initLocale(); //init google nalytics //setAnalyticsService(); } catch (Throwable e) { e.printStackTrace(); Log.e(e); }
- 参考KitchenSink示例,在
maven common/src/main/css目录下添加dark-theme.css后,执行以下切换代码:
try { Resources resources = Resources.openLayered( "/dark-theme" ); UIManager.getInstance().addThemeProps(resources.getTheme(resources.getThemeResourceNames()[0])); Display.getInstance().getCurrent().refreshTheme(); Utility.setTheme(theme); } catch(IOException e){ ComponentUtility.showStatusError("Sorry, unable to switch theme: " + e.getMessage() ); e.printStackTrace(); }
- 执行时出现报错:
java.io.IOException: /dark-theme.res not found,完整堆栈信息:
java.io.IOException: /dark-theme.res not found at com.codename1.ui.util.Resources.open(Resources.java:756) at com.codename1.ui.util.Resources.openLayered(Resources.java:720) at com.codename1.ui.util.Resources.openLayered(Resources.java:684) at net.mailangel.pay.containers.ThemeContainer.update(ThemeContainer.java:111) at net.mailangel.pay.containers.ThemeContainer.lambda$getButttonContainer$0(ThemeContainer.java:58) at com.codename1.ui.util.EventDispatcher.fireActionEvent(EventDispatcher.java:349) at com.codename1.ui.Button.fireActionEvent(Button.java:687) at com.codename1.ui.Button.released(Button.java:728) at com.codename1.ui.Button.pointerReleased(Button.java:835) at com.codename1.ui.LeadUtil.pointerReleased(LeadUtil.java:153) at com.codename1.ui.Form.pointerReleased(Form.java:3881) at com.codename1.ui.Component.pointerReleased(Component.java:5266) at com.codename1.ui.Display.handleEvent(Display.java:2409) at com.codename1.ui.Display.edtLoopImpl(Display.java:1285) at com.codename1.ui.Display.mainEDTLoop(Display.java:1203) at com.codename1.ui.RunnableWrapper.run(RunnableWrapper.java:120) at com.codename1.impl.CodenameOneThread.run(CodenameOneThread.java:176)
环境:IDE为IntelliJ,Java 8,Maven 3.6.3,CodenameOne 7.0.80,项目无build.xml文件。
咨询问题:
- 如何在基于Maven的CodenameOne项目中成功切换CSS主题?
- 如何通过CSS生成.res文件?
解决方案
一、通过CSS生成.res文件
在Maven版CodenameOne项目中,CSS文件需通过Maven插件自动编译为.res资源文件,步骤如下:
- 确保CSS文件放在
common/src/main/css目录下(你已正确放置dark-theme.css); - 在项目根目录执行Maven构建命令:
mvn clean package,CodenameOne的Maven插件会自动将目录下的CSS编译为同名.res文件,输出到common/target/classes目录; - 构建完成后,检查
common/target/classes目录,确认dark-theme.res已生成,该文件会被打包进应用资源中。
二、正确切换CSS主题的步骤
修改主题切换代码,修正资源加载与主题应用逻辑:
- 去掉资源路径前的
/,直接使用文件名即可; - 使用
setThemeProps替换当前主题属性(addThemeProps是追加属性,会导致新旧主题混合); - 更新全局资源并刷新所有已打开窗体的主题。
修改后的切换代码示例:
try { // 加载深色主题资源,无需前缀/ Resources darkTheme = Resources.openLayered("dark-theme"); Hashtable<String, Object> themeProps = darkTheme.getTheme(darkTheme.getThemeResourceNames()[0]); // 完全替换当前主题属性 UIManager.getInstance().setThemeProps(themeProps); // 更新全局资源 Resources.setGlobalResources(darkTheme); // 刷新当前显示的窗体 Display.getInstance().getCurrent().refreshTheme(); // 遍历所有已打开窗体,强制刷新主题 for (Form f : Display.getInstance().getAllForms()) { f.refreshTheme(); } Utility.setTheme("dark-theme"); // 确保参数与主题标识一致 } catch(IOException e){ ComponentUtility.showStatusError("Sorry, unable to switch theme: " + e.getMessage() ); e.printStackTrace(); }
另外,启动时的初始化代码可简化,避免重复叠加主题:
try { // 加载主主题资源 Resources mainResources = Resources.openLayered("MailAngel"); Hashtable<String, Object> mainThemeProps = mainResources.getTheme(mainResources.getThemeResourceNames()[0]); UIManager.getInstance().setThemeProps(mainThemeProps); // 按需叠加浅色主题,确保路径正确 if (Constants.THEME_LIGHT.equals("light-theme")) { Resources lightTheme = Resources.openLayered(Constants.THEME_LIGHT); UIManager.getInstance().addThemeProps(lightTheme.getTheme(lightTheme.getThemeResourceNames()[0])); Resources.setGlobalResources(lightTheme); } initLocale(); } catch (Throwable e) { e.printStackTrace(); Log.e(e); }
内容的提问来源于stack exchange,提问作者Mohammed Hussein
相关产品推荐
相关产品推荐

