JavaFX桌面应用替换HTML响应CSS后ProximaNova字体不生效问题排查
JavaFX WebView加载自定义CSS字体失效问题排查
问题描述
我正在开发基于JavaFX的桌面应用,其中一个界面的部分内容通过PHP接口返回的HTML加载。目标是将HTML响应中的CSS文件替换为自定义CSS文件,目前所有样式属性均已生效,但@font-face引入的ProximaNova.woff字体无法应用。
相关代码
HTML响应
<html subtitle="Please type your activation code in the text box below and click 'Next'. "> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>promotion activation</title> <link type="text/css" rel="stylesheet" href="promotion.css" /> <script> window.addEventListener("load", function() { var evt = document.createEvent("Events"); evt.initEvent("TTUpdateButton", true, false); document.documentElement.dispatchEvent(evt); }, true); </script> </head> <body> <button id="TTButton_continue" disabled="true" onclick="onButtonEvent('right')" style="display: none;"> Next </button> <div id="code-body"> <div id="code-box"> <form name="fcode" id="code-fcode" method="post" onsubmit="return isCodeValid();"> <input type="hidden" name="action" value="validate" /> <div id="code-textbox"> <span> Your activation code </span> <input class="field" type="text" name="sCode" id="code" value="" onchange="onInputChange();" onkeyup="onInputChange();" /> </div> </form> <div id="code-text"> As soon as you activate your code, the associated product will be available for download and/or use.<a href=# onClick="Javascript:onMoreInfoLinkClick()">Learn how you can get your activation code here.</a> </div> </div> </div> <script type="text/javascript"> if (document.fcode) { document.fcode.sCode.focus(); } var initialCodeValue = ""; function isCodeValid() { var theRawValue = document.fcode.sCode.value; // Don't enable the next button if nothing has changed if (theRawValue == initialCodeValue) return false; initialCodeValue = ""; theUpperCaseValue = theRawValue.toUpperCase(); //we need first to clean the input like we do server side theValue = (theUpperCaseValue.replace(/\W+/g,'')); return (theValue.search(/^[a-zA-Z0-9]{11}$|^NC[0-9]{10}$|^CC[0-9]{16}$/) == 0); } function writeScriptOpenTomTomHelpLink() { var evt = document.createEvent("Events"); evt.initEvent("TTHelpLink", true, false); document.documentElement.dispatchEvent(evt); } function onMoreInfoLinkClick(){ writeScriptOpenTomTomHelpLink(); } function onInputChange() { var valid = isCodeValid(); var theButtonElement = document.getElementById("TTButton_continue"); if (valid) theButtonElement.removeAttribute("disabled"); else theButtonElement.setAttribute("disabled", true); var evt = document.createEvent("Events"); evt.initEvent("TTUpdateButton", true, false); document.documentElement.dispatchEvent(evt); } function onButtonEvent(buttonName) { document.fcode.submit(); } window.addEventListener("load", onInputChange, false); </script> </body> </html>
自定义替换CSS文件(MyActivationCode.css)
@font-face { font-family: "proxima"; src: url('/proximanova-regular.woff'); } body { font-family: "proxima"; background: #ffffff; color: #000000; font-size: 13px; } h1 { font-family: proxima; font-weight: bold; font-size: 13px; color: #666666; } .additional-offer { border-top: 3px #dedede solid; } .select-country, .select-product { padding: 5px 10px 15px 10px; } #code-text { margin: 5px 2px 5px 2px; font-family: proxima; } #code-textbox { font-family: "proxima"; margin: 20px 0px 20px 0px; color: #878787; } #code-textbox span { font-family: proxima; font-size: 13px; font-weight: bold; color: #666666; } #code-fcode { display: table-row; text-align: center; height: 100%; } #code-error { color: #ff0000; margin: 0px 2px 5px 2px; font-family: proxima; } #traffic-error { color: #ff0000; margin: 0px 2px 5px 2px; font-family: proxima; } #message-text { margin: 5px 2px 5px 2px; font-family: proxima; } #message-header { font-family: proxima; margin: 20px 0px 20px 0px; font-weight: bold; font-size: 13px; color: #666666; }
DeviceController.java(发起PHP接口请求)
public class DeviceController extends BaseController { @Override protected void doInitialize() { super.doInitialize(); getActivePhpServiceCall(); } /** * Gets the active php service call. * * @return the active php service call */ protected void getActivePhpServiceCall() { new ActivationService().activationCodeService(new FutureCallback<String>() { @Override public void failed(Exception ex) { LOGGER.error("Failed to call Activation code service: {}", ex); } @Override public void completed(String result) { new ActivationCodeHelper().handleBackForActivationCodeService(result); } @Override public void cancelled() { LOGGER.debug("Activation code service call is cancelled"); } }); } }
ActivationCodeHelper.java(替换CSS文件逻辑)
public class ActivationCodeHelper extends BaseHelper { /** * Handle back for activation code service. * * @param result the result */ public void handleBackForActivationCodeService(String result) { Map<String, Object> map = new HashMap<>(); String cssURL = ""; try { cssURL = globalContext.fileUtil().getFileContents(Paths .get(getClass().getClassLoader().getResource("css/MyActivationCode.css").toURI()).toString()); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(cssURL.toString()); File cssFile = globalContext.fileUtil().fileWriter(".css", cssURL); File file = globalContext.fileUtil().fileWriter(".html", result.replaceAll("promotion.css", cssFile.getName())); map.put("cssFile", cssFile.getName()); map.put("UseMyActivation", file.toURI().toString()); redirectToActivationScreen(map); } }
字体失效原因及修复方案
核心原因
- 字体路径错误:CSS中
url('/proximanova-regular.woff')使用了根路径(以/开头),但生成的HTML和CSS是临时文件,JavaFX WebView无法识别这个根路径对应的实际文件位置。 - 字体文件未同步到临时目录:代码仅生成了HTML和CSS临时文件,但没有将字体文件复制到同一目录,导致WebView找不到字体资源。
- 相对路径引用错误:未使用和临时文件目录匹配的相对路径指向字体文件。
修复步骤
复制字体文件到临时目录
在ActivationCodeHelper的handleBackForActivationCodeService方法中,添加代码将字体文件复制到CSS和HTML所在的临时目录:// 假设字体文件放在resources/fonts目录下,根据实际路径调整 URL fontResource = getClass().getClassLoader().getResource("fonts/proximanova-regular.woff"); if (fontResource != null) { try { File fontFile = new File(cssFile.getParentFile(), "proximanova-regular.woff"); Files.copy(Paths.get(fontResource.toURI()), fontFile.toPath(), StandardCopyOption.REPLACE_EXISTING); } catch (IOException | URISyntaxException e) { e.printStackTrace(); } }修改CSS中的字体路径
将@font-face中的路径改为相对路径(因为字体和CSS在同一目录):@font-face { font-family: "proxima"; src: url('proximanova-regular.woff'); }验证文件位置一致性
确保生成的HTML、CSS、字体三个文件都处于同一临时目录下,WebView才能正确加载字体资源。
内容的提问来源于stack exchange,提问作者ksa
相关产品推荐
相关产品推荐

