Java 如何使用JfreeChart将CategoryTextAnnotation锚定在水平条的左上角
我已经厌倦了自己去弄清楚这一点,想知道这是一个已知的bug还是jfreechart库中的一个误解 我有两个栏,希望在每个栏的左上角显示文本“You”和“neighborhood avg.”。与第二幅图中的外观相似 在水平条的左上角获得两个标签位置的正确方法是什么 下面是生成图1的代码:Java 如何使用JfreeChart将CategoryTextAnnotation锚定在水平条的左上角,java,jfreechart,Java,Jfreechart,我已经厌倦了自己去弄清楚这一点,想知道这是一个已知的bug还是jfreechart库中的一个误解 我有两个栏,希望在每个栏的左上角显示文本“You”和“neighborhood avg.”。与第二幅图中的外观相似 在水平条的左上角获得两个标签位置的正确方法是什么 下面是生成图1的代码: @RestController public class JfreeCharCategoryAnnotationBug { @RequestMapping(value = "bug", metho
@RestController
public class JfreeCharCategoryAnnotationBug {
@RequestMapping(value = "bug", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<StreamingResponseBody> getBarChartWithCategoryAnnotationBug(String title) {
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
String youDataKey = "You";
String weDataKey = "Neightborhood Avg.";
Map<TextAttribute, Object> values2X = new HashMap<TextAttribute, Object>();
values2X.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
values2X.put(TextAttribute.SIZE, 20);
Font scaledFont = new Font("Arial Bold", Font.PLAIN, 20).deriveFont(values2X);
barDataSet.setValue(200, youDataKey, youDataKey);
barDataSet.setValue(2000, weDataKey, weDataKey);
JFreeChart barGraph = ChartFactory.createBarChart(null, "", "",
barDataSet, PlotOrientation.HORIZONTAL, true, false, false);
Color weSpendColor = new Color(40, 137, 0);
Color youSpendColor = new Color(48, 35, 174);
// plot manipulations
CategoryPlot plotModifier = barGraph.getCategoryPlot();
barGraph.setBorderVisible(false);
plotModifier.setOutlineVisible(false);
// remove space between axis and data area
plotModifier.setAxisOffset(new RectangleInsets(0.0, 0.0, 0.0, 0.0));
plotModifier.setInsets(new RectangleInsets(0, 0, 0, 0), true);
// Axis modifications
ValueAxis rangeAxis = (ValueAxis) plotModifier.getRangeAxis();
rangeAxis.setVisible(false);
rangeAxis.setAxisLineVisible(false);
CategoryAxis domainAxis = (CategoryAxis) plotModifier.getDomainAxis();
domainAxis.setVisible(false);
domainAxis.setAxisLineStroke(new BasicStroke(4));
domainAxis.setLabelFont(scaledFont);
// Actual data point manipulations
BarRenderer renderer = (BarRenderer) plotModifier.getRenderer();
renderer.setBarPainter(new StandardBarPainter());
renderer.setBaseItemLabelsVisible(true);
renderer.setDrawBarOutline(true);
renderer.setBaseItemLabelGenerator(new CategoryItemLabelGenerator() {
@Override
public String generateRowLabel(CategoryDataset dataset, int row) {
return dataset.getRowKey(row).toString();
}
@Override
public String generateLabel(CategoryDataset dataset, int row,
int column) {
Number value = dataset.getValue(row, column);
StringBuilder sb = new StringBuilder("$");
// return sb.append(format(value.longValue())).toString();
return sb.append(value.longValue()).toString();
}
@Override
public String generateColumnLabel(CategoryDataset dataset,
int column) {
return dataset.getColumnKey(column).toString();
}
});
renderer.setBaseItemLabelFont(scaledFont);
// Color time
renderer.setSeriesPaint(0, youSpendColor, true);
renderer.setSeriesPaint(1, weSpendColor, true);
renderer.setSeriesOutlinePaint(0, youSpendColor, true);
renderer.setSeriesOutlinePaint(1, weSpendColor, true);
domainAxis.setAxisLinePaint(Color.GREEN);
plotModifier.setBackgroundPaint(Color.WHITE);
// margins and offsets
renderer.setItemMargin(0);
// for item label i.e $1K
renderer.setItemLabelAnchorOffset(2);
plotModifier.getDomainAxis().setCategoryMargin(0.0);
// for space between the plot outline and the bar
plotModifier.getDomainAxis().setLowerMargin(0.30);
plotModifier.getDomainAxis().setUpperMargin(0.0);
plotModifier.getRangeAxis().setLowerMargin(0.0);
// brings back some of the item text
plotModifier.getRangeAxis().setUpperMargin(0.30);
// annotations
CategoryTextAnnotation we = new CategoryTextAnnotation(weDataKey,weDataKey, 0.0D);
CategoryTextAnnotation you = new CategoryTextAnnotation(youDataKey,youDataKey, 0.0D);
you.setFont(scaledFont);
we.setFont(scaledFont);
you.setPaint(new Color(135, 144, 153));
we.setPaint(new Color(135, 144, 153));
you.setCategoryAnchor(CategoryAnchor.START);
we.setCategoryAnchor(CategoryAnchor.START);
// possibly a jFreeChart bug Bottom_LEFT aligns first category's annotation to the position that TOP_LEFT should/does anchors the second category annotation
you.setTextAnchor(TextAnchor.TOP_LEFT);
we.setTextAnchor(TextAnchor.TOP_LEFT);
plotModifier.addAnnotation(you);
plotModifier.addAnnotation(we);
barGraph.removeLegend();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// creating a chart with double the pixels for better rendering when client "auto layout" on mobile device
ChartUtilities.writeBufferedImageAsPNG(baos, barGraph.createBufferedImage(480,160, new ChartRenderingInfo()));
} catch (IOException e) {
//omitted
}
MultiValueMap<String, String> responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE);
return new ResponseEntity<StreamingResponseBody>(
new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
baos.writeTo(outputStream);
}
}, responseHeaders, HttpStatus.OK);
}
}
@RestController
公共类JfreeCharCategoryAnnotationBug{
@RequestMapping(value=“bug”,method=RequestMethod.GET,products=MediaType.IMAGE\u PNG\u value)
公共响应标题getBarChartWithCategoryAnnotationBug(字符串标题){
DefaultCategoryDataset barDataSet=新的DefaultCategoryDataset();
字符串youDataKey=“You”;
字符串weDataKey=“Neightborhood Avg.”;
Map values2X=新的HashMap();
值2x.put(texttribute.KERNING,texttribute.KERNING_ON);
值2x.put(TextAttribute.SIZE,20);
Font scaledFont=新字体(“Arial粗体”,Font.PLAIN,20)。衍生字体(值2x);
设置值(200,youDataKey,youDataKey);
设置值(2000,weDataKey,weDataKey);
JFreeChart barGraph=ChartFactory.createBarChart(空,“”,“”,
barDataSet、PlotOrientation.HORIZONTAL、true、false、false);
颜色weSpendColor=新颜色(40,137,0);
颜色youSpendColor=新颜色(48,35,174);
//情节操纵
CategoryPlot plotModifier=barGraph.getCategoryPlot();
条形图可见(假);
plotModifier.setOutlineVisible(false);
//删除轴和数据区域之间的空间
setAxisOffset(新的矩形插入(0.0,0.0,0.0,0.0));
plotModifier.setInsets(新的矩形插入(0,0,0,0),true);
//轴修改
ValueAxis rangeAxis=(ValueAxis)plotModifier.getRangeAxis();
rangeAxis.setVisible(假);
rangeAxis.setAxisLineVisible(false);
CategoryAxis domainAxis=(CategoryAxis)plotModifier.getDomainAxis();
domainAxis.setVisible(false);
domainAxis.setAxisLineStroke(新BasicStroke(4));
domainAxis.setLabelFont(scaledFont);
//实际数据点操作
BarRenderer renderer=(BarRenderer)plotModifier.getRenderer();
renderer.setBarPainter(新的StandardBarPainter());
renderer.setBaseItemLabelsVisible(true);
renderer.setroutline(true);
renderer.setBaseItemLabelGenerator(新类别ItemLabelGenerator(){
@凌驾
公共字符串生成器WLabel(CategoryDataset数据集,int行){
返回dataset.getRowKey(row.toString();
}
@凌驾
公共字符串generateLabel(CategoryDataset数据集,int行,
int列){
数值=dataset.getValue(行、列);
StringBuilder sb=新的StringBuilder($);
//返回sb.append(格式(value.longValue()).toString();
返回sb.append(value.longValue()).toString();
}
@凌驾
公共字符串generateColumnLabel(CategoryDataset数据集,
int列){
返回dataset.getColumnKey(column.toString();
}
});
renderer.setBaseItemLabelFont(缩放字体);
//彩色时间
renderer.setSeriesPaint(0,youSpendColor,true);
renderer.setSeriesPaint(1,weSpendColor,true);
renderer.setSeriesOutlinePaint(0,youSpendColor,true);
renderer.setSeriesOutlinePaint(1,weSpendColor,true);
domainAxis.setAxisLinePaint(颜色.绿色);
plotModifier.setBackgroundPaint(颜色:白色);
//差额和抵销
setItemMargin(0);
//对于项目标签,即$1K
渲染器.setItemLabelAnchorOffset(2);
plotModifier.getDomainAxis().setCategoryMargin(0.0);
//用于显示打印轮廓和条形图之间的空间
plotModifier.getDomainAxis().setLowerMargin(0.30);
plotModifier.getDomainAxis().setUpperMargin(0.0);
plotModifier.getRangeAxis().setLowerMargin(0.0);
//返回部分项目文本
plotModifier.getRangeAxis().setUpperMargin(0.30);
//注释
CategoryTextAnnotation we=新的CategoryTextAnnotation(weDataKey,weDataKey,0.0D);
CategoryTextAnnotation you=新的CategoryTextAnnotation(youDataKey,youDataKey,0.0D);
you.setFont(scaledFont);
we.setFont(scaledFont);
you.setPaint(新颜色(135144153));
we.setPaint(新颜色(135144153));
you.setCategoryAnchor(CategoryAnchor.START);
we.setCategoryAnchor(CategoryAnchor.START);
//可能是jFreeChart错误“左下”将第一个类别的注释与“左上”应该/确实锚定第二个类别注释的位置对齐
you.setTextAnchor(textachor.TOP_左上角);
we.setTextAnchor(textachor.TOP_左上角);
plotModifier.addAnnotation(您);
plotModifier.addAnnotation(we);
条形图。removeLegend();
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
试一试{
//当客户端在移动设备上“自动布局”时,创建具有两倍像素的图表以更好地呈现
writeBufferedImageAsPNG(baos,barGraph.CreateBuffereImage(480160,new ChartRenderingInfo());
}捕获(IOE异常){
//省略
}
多值映射响应头=新的HttpHeaders();
responseHeaders.set(HttpHeaders.CONTENT\u TYPE、MediaType.IMAGE\u PNG\u值);
返回新响应(
新StreamingResponseBody(){
@凌驾
公共空间w
@RestController
public class JfreeCharCategoryAnnotationBug {
@RequestMapping(value = "bug", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
public ResponseEntity<StreamingResponseBody> getBarChartWithCategoryAnnotationBug(String title) {
DefaultCategoryDataset barDataSet = new DefaultCategoryDataset();
String youDataKey = "You";
String weDataKey = "Neightborhood Avg.";
Map<TextAttribute, Object> values2X = new HashMap<TextAttribute, Object>();
values2X.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
values2X.put(TextAttribute.SIZE, 20);
Font scaledFont = new Font("Arial Bold", Font.PLAIN, 20).deriveFont(values2X);
barDataSet.setValue(200, youDataKey, youDataKey);
barDataSet.setValue(2000, weDataKey, weDataKey);
JFreeChart barGraph = ChartFactory.createBarChart(null, "", "",
barDataSet, PlotOrientation.HORIZONTAL, true, false, false);
Color weSpendColor = new Color(40, 137, 0);
Color youSpendColor = new Color(48, 35, 174);
// plot manipulations
CategoryPlot plotModifier = barGraph.getCategoryPlot();
barGraph.setBorderVisible(false);
plotModifier.setOutlineVisible(false);
// remove space between axis and data area
plotModifier.setAxisOffset(new RectangleInsets(0.0, 0.0, 0.0, 0.0));
plotModifier.setInsets(new RectangleInsets(0, 0, 0, 0), true);
// Axis modifications
ValueAxis rangeAxis = (ValueAxis) plotModifier.getRangeAxis();
rangeAxis.setVisible(false);
rangeAxis.setAxisLineVisible(false);
CategoryAxis domainAxis = (CategoryAxis) plotModifier.getDomainAxis();
domainAxis.setVisible(false);
domainAxis.setAxisLineStroke(new BasicStroke(4));
domainAxis.setLabelFont(scaledFont);
// Actual data point manipulations
BarRenderer renderer = (BarRenderer) plotModifier.getRenderer();
renderer.setBarPainter(new StandardBarPainter());
renderer.setBaseItemLabelsVisible(true);
renderer.setDrawBarOutline(true);
renderer.setBaseItemLabelGenerator(new CategoryItemLabelGenerator() {
@Override
public String generateRowLabel(CategoryDataset dataset, int row) {
return dataset.getRowKey(row).toString();
}
@Override
public String generateLabel(CategoryDataset dataset, int row,
int column) {
Number value = dataset.getValue(row, column);
StringBuilder sb = new StringBuilder("$");
// return sb.append(format(value.longValue())).toString();
return sb.append(value.longValue()).toString();
}
@Override
public String generateColumnLabel(CategoryDataset dataset,
int column) {
return dataset.getColumnKey(column).toString();
}
});
renderer.setBaseItemLabelFont(scaledFont);
// Color time
renderer.setSeriesPaint(0, youSpendColor, true);
renderer.setSeriesPaint(1, weSpendColor, true);
renderer.setSeriesOutlinePaint(0, youSpendColor, true);
renderer.setSeriesOutlinePaint(1, weSpendColor, true);
domainAxis.setAxisLinePaint(Color.GREEN);
plotModifier.setBackgroundPaint(Color.WHITE);
// margins and offsets
renderer.setItemMargin(0);
// for item label i.e $1K
renderer.setItemLabelAnchorOffset(2);
plotModifier.getDomainAxis().setCategoryMargin(0.0);
// for space between the plot outline and the bar
plotModifier.getDomainAxis().setLowerMargin(0.30);
plotModifier.getDomainAxis().setUpperMargin(0.0);
plotModifier.getRangeAxis().setLowerMargin(0.0);
// brings back some of the item text
plotModifier.getRangeAxis().setUpperMargin(0.30);
// annotations
CategoryTextAnnotation we = new CategoryTextAnnotation(weDataKey,weDataKey, 0.0D);
CategoryTextAnnotation you = new CategoryTextAnnotation(youDataKey,youDataKey, 0.0D);
you.setFont(scaledFont);
we.setFont(scaledFont);
you.setPaint(new Color(135, 144, 153));
we.setPaint(new Color(135, 144, 153));
you.setCategoryAnchor(CategoryAnchor.START);
we.setCategoryAnchor(CategoryAnchor.START);
// possibly a jFreeChart bug Bottom_LEFT aligns first category's annotation to the position that TOP_LEFT should/does anchors the second category annotation
you.setTextAnchor(TextAnchor.BOTTOM_LEFT);
we.setTextAnchor(TextAnchor.TOP_LEFT);
plotModifier.addAnnotation(you);
plotModifier.addAnnotation(we);
barGraph.removeLegend();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
// creating a chart with double the pixels for better rendering when client "auto layout" on mobile device
ChartUtilities.writeBufferedImageAsPNG(baos, barGraph.createBufferedImage(480,160, new ChartRenderingInfo()));
} catch (IOException e) {
//omitted
}
MultiValueMap<String, String> responseHeaders = new HttpHeaders();
responseHeaders.set(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE);
return new ResponseEntity<StreamingResponseBody>(
new StreamingResponseBody() {
@Override
public void writeTo(OutputStream outputStream) throws IOException {
baos.writeTo(outputStream);
}
}, responseHeaders, HttpStatus.OK);
}
}