我正在开发一个使用 JFreeChart 来呈现图表的 Web 应用程序。但是,当服务器没有安装任何中文字体时,即使我设置了字体,JFreeChart 也不显示中文字符。
然后我写了一个小测试代码,发现在绘制图表之前添加这行代码可以解决问题。
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font);
所以我的问题是——
为什么即使我从文件创建字体,我也必须将字体注册到 JVM 中?这是否意味着 JFreeChart 不使用我直接设置的字体?
当我将程序部署到服务器时,即使我添加了这行代码,它也不显示汉字。如何让它始终使用我设置的字体以便在所有环境中正确显示字符?
我知道我可以创建一个fallback
目录$JAVA_HOME/jre/lib
并将我的字体放入其中。但这并不能解释为什么 JFreeChart 不能用我设置的字体显示。
更新
我很确定字体已正确加载,registerFont()
当我将程序部署到 Tomcat 时也返回 true。
更新 2
根据JAVA 2D FAQ,现在我意识到我必须调用registerFont()
才能将我自己的字体“安装”到 JVM 中,并且我的字体将通过Font
构造函数可用。
从 Java SE 6 开始,有一个方法:GraphicsEnvironment.registerFont(),它使您能够使“创建的”字体可用于 Font 构造函数并通过 Font 枚举 API 列出。Font.createFont() 和这个方法结合起来提供了一种将字体“安装”到正在运行的 JRE 中的方法,因此它就像 O/S 安装的字体一样可用。但是,此字体不会在 JRE 调用中持续存在。
但是,既然我已经Font
创建/派生了实例createFont()
,为什么我的程序还不需要创建其他的Font
?
以下是我使用的代码,它只是以 PNG 格式输出图表。如果你想运行代码,你应该改变输出位置和字体以满足你的需要,这里是我在代码中使用的中文字体的 SourceForge 链接。
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.File;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
public class Problem {
public static void main(String[] args) throws Exception {
setJFreeChartTheme();
PieDataset dataset = createDataSet();
JFreeChart chart = ChartFactory.createPieChart(
"Chinese Testing", dataset, true, true, false);
ChartUtilities.saveChartAsJPEG(new File("/tmp/output.png"),
chart, 800, 600);
System.out.println("Done");
}
private static void setJFreeChartTheme() throws Exception {
Font font = loadFont();
//==================================================================
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font);
//==================================================================
StandardChartTheme theme = new StandardChartTheme("Chinese font", true);
theme.setExtraLargeFont(font.deriveFont(Font.BOLD, 20));
theme.setLargeFont(font.deriveFont(Font.BOLD, 16));
theme.setRegularFont(font.deriveFont(Font.PLAIN, 14));
theme.setSmallFont(font.deriveFont(Font.PLAIN, 12));
ChartFactory.setChartTheme(theme);
}
private static Font loadFont() throws Exception {
File file = new File("/tmp/wqy-zenhei.ttc");
return Font.createFont(Font.TRUETYPE_FONT, file);
}
private static PieDataset createDataSet() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("種類1", Integer.valueOf(1));
dataset.setValue("種類2", Integer.valueOf(2));
dataset.setValue("種類3", Integer.valueOf(3));
return dataset;
}
}