Java JFreeChart类别图像

Java JFreeChart类别图像,java,jfreechart,Java,Jfreechart,是否有任何方法可以在类别字符串旁边添加图像,如这些附件所示 当前: 期望的: 编辑: 根据kiwiwings的回答,我在他的演示中轻松地在XYchart的标签字符串旁边显示了我的图像: protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {

是否有任何方法可以在类别字符串旁边添加图像,如这些附件所示

当前:

期望的:

编辑:

根据kiwiwings的回答,我在他的演示中轻松地在XYchart的标签字符串旁边显示了我的图像:

    protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor, Rectangle2D plotArea, Rectangle2D dataArea,
            RectangleEdge edge) {

        if (isTickLabelsVisible()) {
            Shape s = xyRend.getBaseShape();
            Paint oldPaint = g2.getPaint();
            g2.setPaint(xyRend.getSeriesPaint(0));
            Rectangle2D rect = s.getBounds2D();
            AffineTransform oldTrans = g2.getTransform();

            AxisState state = new AxisState(cursor);
            @SuppressWarnings("unchecked")
            List<ValueTick> ticks = (List<ValueTick>) refreshTicks(g2, state, dataArea, edge);
            for (ValueTick tick : ticks) {
                float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
                g2.setTransform(oldTrans);
                // TODO: replace "anchorPoint[0]-X" with a bounds based value
                g2.translate(anchorPoint[0] - 28, anchorPoint[1] + 2);
                BufferedImage bfrImg = * load img here *;
                g2.drawImage(bfrImg, 0, 0, null);
            }

            g2.setPaint(oldPaint);
            g2.setTransform(oldTrans);
        }

        return super.drawTickMarksAndLabels(g2, cursor, plotArea, dataArea, edge);
    }
是的,有

形状位置的计算有点过于复杂,但我希望它能解决您的问题。如果你想拥有图例的形状,你需要使用

Shape s = xyRend.getLegendItem(0, 0).getShape();
并调整y位置

import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.util.List;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.time.*;
import org.jfree.ui.*;

public class CategoryLabelWithShape extends ApplicationFrame {

    public CategoryLabelWithShape(final String title) {
        super(title);
        final JFreeChart chart = constructChart();
        final ChartPanel panel = new ChartPanel(chart);
        setContentPane(panel);
    }

    JFreeChart constructChart() {
        JFreeChart chart = ChartFactory.createXYBarChart(
            "State Executions","Year",true,"Number of people",getDataSet(),PlotOrientation.VERTICAL,true,true,false
        );

        XYPlot xyPlot = (XYPlot)chart.getPlot();
        final XYItemRenderer xyRend = xyPlot.getRenderer();

        DateAxis daNew = new DateAxis(){
            /**
             * Draws the axis line, tick marks and tick mark labels.
             *
             * @param g2  the graphics device.
             * @param cursor  the cursor.
             * @param plotArea  the plot area.
             * @param dataArea  the data area.
             * @param edge  the edge that the axis is aligned with.
             *
             * @return The width or height used to draw the axis.
             */
            protected AxisState drawTickMarksAndLabels(Graphics2D g2,
                    double cursor, Rectangle2D plotArea, Rectangle2D dataArea,
                    RectangleEdge edge) {

                if (isTickLabelsVisible()) {
                    Shape s = xyRend.getBaseShape();
                    Paint oldPaint = g2.getPaint();
                    g2.setPaint(xyRend.getSeriesPaint(0));
                    Rectangle2D rect = s.getBounds2D();
                    AffineTransform oldTrans = g2.getTransform();

                    AxisState state = new AxisState(cursor);
                    @SuppressWarnings("unchecked")
                    List<ValueTick> ticks = (List<ValueTick>)refreshTicks(g2, state, dataArea, edge);
                    for (ValueTick tick : ticks) {
                        float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
                        g2.setTransform(oldTrans);
                        // TODO: replace "anchorPoint[0]-X" with a bounds based value
                        g2.translate(anchorPoint[0]-17, anchorPoint[1]+rect.getHeight());
                        g2.fill(s);
                    }


                    g2.setPaint(oldPaint);
                    g2.setTransform(oldTrans);
                }

                return super.drawTickMarksAndLabels(g2,cursor,plotArea,dataArea,edge);
            }
        };

        daNew.setLabel(xyPlot.getDomainAxis().getLabel());
        xyPlot.setDomainAxis(daNew);

        return chart;
    }

    private TimeSeriesCollection getDataSet() {
        TimeSeriesCollection ds = new TimeSeriesCollection();

        final TimeSeries s1 = new TimeSeries("Executions");
        ds.addSeries(s1);

        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(Calendar.YEAR, 1970);
        Random rand = new Random();
        for (int i=0; i<(2010-1970); i++) {
            s1.add(new Year(cal.getTime()), rand.nextInt(100));
            cal.add(Calendar.YEAR, 1);
        }

        return ds;
    }


    public static void main(String[] args) {
        CategoryLabelWithShape demo = new CategoryLabelWithShape(
                "Category-label with a shape");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}
import java.awt.*;
导入java.awt.geom.*;
导入java.util.*;
导入java.util.List;
导入org.jfree.chart.*;
导入org.jfree.chart.axis.*;
导入org.jfree.chart.plot.*;
导入org.jfree.chart.renderer.xy.XYItemRenderer;
导入org.jfree.data.time.*;
导入org.jfree.ui.*;
公共类CategoryLabelWithShape扩展了ApplicationFrame{
公共类别带形状的标签(最终字符串标题){
超级(标题);
最终JFreeChart chart=constructChart();
最终图表面板=新图表面板(图表);
设置内容窗格(面板);
}
JFreeChart构造图(){
JFreeChart chart=ChartFactory.createXYBarChart(
“状态执行”、“年份”、“真”、“人数”、getDataSet()、PlotOrientation.VERTICAL、true、true、false
);
XYPlot XYPlot=(XYPlot)chart.getPlot();
final XYItemRenderer xyRend=xyPlot.getRenderer();
DateAxis daNew=新的DateAxis(){
/**
*绘制轴线、记号和记号标签。
*
*@param g2用于图形设备。
*@param cursor指向光标。
*@param plotArea打印区域。
*@param dataArea数据区域。
*@param edge轴与之对齐的边。
*
*@返回用于绘制轴的宽度或高度。
*/
受保护的AxisState图纸标记和标签(图形2D g2,
双光标、矩形2D绘图区、矩形2D数据区、,
矩形边缘){
if(belsvisible()){
Shape s=xyRend.getBaseShape();
绘制oldPaint=g2.getPaint();
g2.setPaint(xyRend.getSeriesPaint(0));
矩形2D rect=s.getBounds2D();
仿射变换oldTrans=g2.getTransform();
AxisState=新AxisState(光标);
@抑制警告(“未选中”)
列表标记=(列表)刷新标记(g2、状态、数据区、边缘);
对于(ValueTick勾号:勾号){
float[]锚点=计算锚点(勾号、光标、数据区、边缘);
g2.setTransform(oldTrans);
//TODO:将“anchorPoint[0]-X”替换为基于边界的值
g2.translate(主播点[0]-17,主播点[1]+rect.getHeight());
g2.填充;
}
g2.setPaint(旧漆);
g2.setTransform(oldTrans);
}
返回super.drawTickMarksAndLabels(g2、光标、绘图区、数据区、边缘);
}
};
setLabel(xyPlot.getDomainAxis().getLabel());
xyPlot.setDomainAxis(daNew);
收益表;
}
私有时间体验集合getDataSet(){
TimeSeriesCollection ds=新TimeSeriesCollection();
最终时间序列s1=新时间序列(“执行”);
ds.addSeries(s1);
Calendar cal=Calendar.getInstance();
cal.clear();
校准集(日历年,1970年);
Random rand=新的Random();

对于(int i=0;我只需要使用随机图像,而不是图例。我会查看您的代码。谢谢!我猜它可能是某种政治党派标志……今晚我会看一看。请指定图像和年份的对应方式,如果有关系,什么时候会因为图表宽度限制而跳过一年许可党标志?这是这只是我从JFreeChart网站上得到的一个演示屏幕截图,我的图表只是一个X轴上有国家字符串的条形图,我想在旁边添加国家国旗,所以每个值下都有不同的图像。就像在政治上一样…共和党/民主党我更新了我的版本…也许把国旗放在类别下面会更好很多!我由于类别数量和字符数量可变,我在尝试显示图像和字符串时遇到了一些麻烦。为简单起见,我放弃了字符串,只在类别空间的中心显示标志。
import java.awt.*;
import java.awt.geom.*;
import java.util.*;
import java.util.List;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.time.*;
import org.jfree.ui.*;

public class CategoryLabelWithShape extends ApplicationFrame {

    public CategoryLabelWithShape(final String title) {
        super(title);
        final JFreeChart chart = constructChart();
        final ChartPanel panel = new ChartPanel(chart);
        setContentPane(panel);
    }

    JFreeChart constructChart() {
        JFreeChart chart = ChartFactory.createXYBarChart(
            "State Executions","Year",true,"Number of people",getDataSet(),PlotOrientation.VERTICAL,true,true,false
        );

        XYPlot xyPlot = (XYPlot)chart.getPlot();
        final XYItemRenderer xyRend = xyPlot.getRenderer();

        DateAxis daNew = new DateAxis(){
            /**
             * Draws the axis line, tick marks and tick mark labels.
             *
             * @param g2  the graphics device.
             * @param cursor  the cursor.
             * @param plotArea  the plot area.
             * @param dataArea  the data area.
             * @param edge  the edge that the axis is aligned with.
             *
             * @return The width or height used to draw the axis.
             */
            protected AxisState drawTickMarksAndLabels(Graphics2D g2,
                    double cursor, Rectangle2D plotArea, Rectangle2D dataArea,
                    RectangleEdge edge) {

                if (isTickLabelsVisible()) {
                    Shape s = xyRend.getBaseShape();
                    Paint oldPaint = g2.getPaint();
                    g2.setPaint(xyRend.getSeriesPaint(0));
                    Rectangle2D rect = s.getBounds2D();
                    AffineTransform oldTrans = g2.getTransform();

                    AxisState state = new AxisState(cursor);
                    @SuppressWarnings("unchecked")
                    List<ValueTick> ticks = (List<ValueTick>)refreshTicks(g2, state, dataArea, edge);
                    for (ValueTick tick : ticks) {
                        float[] anchorPoint = calculateAnchorPoint(tick, cursor, dataArea, edge);
                        g2.setTransform(oldTrans);
                        // TODO: replace "anchorPoint[0]-X" with a bounds based value
                        g2.translate(anchorPoint[0]-17, anchorPoint[1]+rect.getHeight());
                        g2.fill(s);
                    }


                    g2.setPaint(oldPaint);
                    g2.setTransform(oldTrans);
                }

                return super.drawTickMarksAndLabels(g2,cursor,plotArea,dataArea,edge);
            }
        };

        daNew.setLabel(xyPlot.getDomainAxis().getLabel());
        xyPlot.setDomainAxis(daNew);

        return chart;
    }

    private TimeSeriesCollection getDataSet() {
        TimeSeriesCollection ds = new TimeSeriesCollection();

        final TimeSeries s1 = new TimeSeries("Executions");
        ds.addSeries(s1);

        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(Calendar.YEAR, 1970);
        Random rand = new Random();
        for (int i=0; i<(2010-1970); i++) {
            s1.add(new Year(cal.getTime()), rand.nextInt(100));
            cal.add(Calendar.YEAR, 1);
        }

        return ds;
    }


    public static void main(String[] args) {
        CategoryLabelWithShape demo = new CategoryLabelWithShape(
                "Category-label with a shape");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.net.URL;
import java.util.List;
import javax.imageio.ImageIO;
import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.*;
import org.jfree.data.category.*;
import org.jfree.ui.*;

@SuppressWarnings("serial")
public class CategoryLabelWithShape extends ApplicationFrame {

    public CategoryLabelWithShape(final String title) {
        super(title);
        final JFreeChart chart = constructChart();
        final ChartPanel panel = new ChartPanel(chart);
        setContentPane(panel);
    }

    JFreeChart constructChart() {
        JFreeChart chart = ChartFactory.createBarChart(
            "MEP seats","country","# seats",getDataSet(),PlotOrientation.VERTICAL,true,true,false
        );

        CategoryPlot cp = chart.getCategoryPlot();

        CategoryAxis daNew = new CategoryAxis(){
            protected AxisState drawCategoryLabels(Graphics2D g2,
                    Rectangle2D plotArea,
                    Rectangle2D dataArea,
                    RectangleEdge edge,
                    AxisState state,
                    PlotRenderingInfo plotState) {

                if (isTickLabelsVisible()) {
                    List<CategoryTick> ticks = (List<CategoryTick>)refreshTicks(g2, state, plotArea, edge);

                    int categoryIndex = 0;
                    for (CategoryTick tick : ticks) {
                        double x0 = getCategoryStart(categoryIndex, ticks.size(), dataArea, edge);
                        double y0 = state.getCursor() + getCategoryLabelPositionOffset();


                        CountryFlag cf = (CountryFlag)((CategoryPlot)getPlot()).getDataset().getColumnKey(categoryIndex);
                        try {
                            BufferedImage img = ImageIO.read(new URL(cf.flagUrl));

                            g2.drawImage(img, (int)(x0-img.getWidth()), (int)(y0), img.getWidth(), img.getHeight(), Color.black, null);
                        } catch (IOException e) {
                            // skip flag
                        }

                        categoryIndex++;
                    }
                }               
                return super.drawCategoryLabels(g2, plotArea, dataArea, edge, state, plotState);
            }
        };

        daNew.setLabel(cp.getDomainAxis().getLabel());
        cp.setDomainAxis(daNew);

        return chart;
    }

    static class CountryFlag implements Comparable<CountryFlag> {
        String name, flagUrl;
        CountryFlag(String name, String flagUrl) {
            this.name = name;
            this.flagUrl = flagUrl;
        }
        public int compareTo(CountryFlag o) {
            return name.compareTo(o.name);
        }
        public String toString() {
            return name;
        }
    }

    private CategoryDataset getDataSet() {
        DefaultCategoryDataset ds = new DefaultCategoryDataset();
        ds.addValue(99, "MEP seats", new CountryFlag("Germany","http://upload.wikimedia.org/wikipedia/en/thumb/b/ba/Flag_of_Germany.svg/22px-Flag_of_Germany.svg.png"));
        ds.addValue(72, "MEP seats", new CountryFlag("France","http://upload.wikimedia.org/wikipedia/en/thumb/c/c3/Flag_of_France.svg/22px-Flag_of_France.svg.png"));
        ds.addValue(72, "MEP seats", new CountryFlag("Italy","http://upload.wikimedia.org/wikipedia/en/thumb/0/03/Flag_of_Italy.svg/22px-Flag_of_Italy.svg.png"));
        ds.addValue(72, "MEP seats", new CountryFlag("United Kingdom","http://upload.wikimedia.org/wikipedia/en/thumb/a/ae/Flag_of_the_United_Kingdom.svg/22px-Flag_of_the_United_Kingdom.svg.png"));
        ds.addValue(50, "MEP seats", new CountryFlag("Spain","http://upload.wikimedia.org/wikipedia/en/thumb/9/9a/Flag_of_Spain.svg/22px-Flag_of_Spain.svg.png"));
        ds.addValue(50, "MEP seats", new CountryFlag("Poland","http://upload.wikimedia.org/wikipedia/en/thumb/1/12/Flag_of_Poland.svg/22px-Flag_of_Poland.svg.png"));
        ds.addValue(33, "MEP seats", new CountryFlag("Romania","http://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flag_of_Romania.svg/22px-Flag_of_Romania.svg.png"));
        ds.addValue(25, "MEP seats", new CountryFlag("Netherlands","http://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Flag_of_the_Netherlands.svg/22px-Flag_of_the_Netherlands.svg.png"));
        ds.addValue(22, "MEP seats", new CountryFlag("Belgium","http://upload.wikimedia.org/wikipedia/commons/thumb/9/92/Flag_of_Belgium_%28civil%29.svg/22px-Flag_of_Belgium_%28civil%29.svg.png"));
        ds.addValue(22, "MEP seats", new CountryFlag("Czech Republic","http://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Flag_of_the_Czech_Republic.svg/22px-Flag_of_the_Czech_Republic.svg.png"));
        return ds;
    }


    public static void main(String[] args) {
        CategoryLabelWithShape demo = new CategoryLabelWithShape(
                "Category-label with a shape");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }
}