作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在开发一个使用JFreeChart呈现图表的Web应用程序。但是,当服务器未安装任何中文字体时,即使我设置了字体,JFreeChart也不显示中文字符。
然后,我编写了一个小的测试代码,发现在绘制图表之前添加这行代码可以解决问题。
GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font);
所以我的问题是-
fallback
中创建一个
$JAVA_HOME/jre/lib
目录,并将字体放入其中。但这不能解释为什么JFreeChart无法使用我设置的字体显示。
registerFont()
也返回true。
registerFont()
才能将自己的字体“安装”到JVM中,并且可以通过
Font
构造函数使用我的字体。
Font
创建/派生了
createFont()
实例,为什么我的程序仍不需要创建其他
Font
?
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;
}
}
最佳答案
当直接从TTF创建Font
时,Java显然知道从该单个Font对象中获取字体文件本身的副本的位置。那么,为什么还需要注册该字体才能使用它? 答案是,它不一定总是必须注册,或者至少在整个控制链中直接使用原始Font
对象时才注册。
当Java尝试渲染字体时,真正发生了什么?
区别在于JFreeChart如何要求呈现文本。文本的呈现是通过jcommon的TextUtilities#drawRotatedString
方法执行的。在JDK7上,默认情况下,此方法将:
AttributedString
Graphics2D#drawString
,然后TextLayout
对象。 TextLayout
是选择要提供给
Graphics2D
的实际Font对象的类。
TextLayout
旨在通过使用自动字体选择为字符串的每一段查找合适的字体来支持使用各种字体(即使需要使用多种字体来呈现相同的单个源字符串)来呈现多语言文本。
Font
派生而来的。如果您提供的字体无法呈现输入字符串中的所有字符,则该属性用于选择相似的字体以用于需要使用其他字体的那些文本运行。
Font
对象Font#getFont
以获取与提供的属性匹配的字体(请参见TextLayout#singleFont
),以及GraphicsEnvironment#registerFont
),那么静态
Font#getFont
方法将必须继续执行的操作是包含字体系列名称的属性字符串。它不知道在哪里访问包含对TTF的引用的Font对象,更不用说实际渲染字体所需的任何数据了。
Font
对象呈现文本。碰巧的是,
TextLayout
的另一个构造函数直接接受
Font
对象,而不是一组用于查找字体的属性。
TextUtilities#drawRotatedString
中,可以使用特殊的配置参数来强制JFreeChart使用您提供的确切
TextLayout
对象构造
Font
对象本身。
jcommon.properties
的资源文件(应该以您的类路径/ JAR的根目录结尾),然后创建org.jfree.text.UseDrawRotatedStringWorkaround=true
TextUtilities.setUseDrawRotatedStringWorkaround(true)
关于java - 为什么我的Font是从文件创建的,为什么还要调用GraphicsEnvorinment.registerFont()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12112353/
我是一名优秀的程序员,十分优秀!