是否可以为条形图中的每个类别自定义标签?

时间:2012-06-07 11:04:52

标签: java jfreechart

最近我要求创建一个显示每个项目数据的条形图。这是一个例子:

Example of the bar chart

如您所见,Category是项目的名称,Series是该项目中不同类型的数据。

但是,由于系统不能保证项目名称的唯一性,因此将其用作类别会导致问题,我将无法使用项目名称为不同的项目生成URL。另一方面,如果我使用唯一ID作为类别,我将无法显示项目名称。这让我陷入困境。

所以我的问题是:

有没有办法在JFreeChart中动态生成自定义类别标签?

类似于CategoryItemLabelGenerator的东西,但类别本身。所以我可以使用唯一ID作为类别,但在图表中显示项目名称。

2 个答案:

答案 0 :(得分:4)

答案取决于您所选择的CategoryDataset如何实现KeyedValues2D界面。接口期望密钥是唯一的,默认实现DefaultKeyedValues2D要求密钥为Comparable且不可变。

唯一String实例是典型的具体参数类型,但JFreeChart中没有任何内容强制执行唯一约束。一种方法是将String包装在一个实现Comparable的类中,并强制执行唯一性。 class Valueexample,可利用基础Double实施。您的实现需要一个额外的属性来区分一个project形式,可能使用源关系的主键。您可以覆盖toString()以获取名称的格式化表示。

答案 1 :(得分:2)

这是我实施UniqueValue

的方式
public class UniqueValue implements Comparable<UniqueValue> {

    private final String uniqueId;
    private final String value;

    public UniqueValue(String uniqueId, String value) {
        this.uniqueId = uniqueId;
        this.value = value;
    }

    @Override
    public int compareTo(UniqueValue o) {
        return uniqueId.compareTo(o.uniqueId);
    }

    @Override
    public int hashCode() {
        return uniqueId.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj instanceof UniqueValue) {
            return uniqueId.equals(((UniqueValue)obj).uniqueId);
        }
        return false;
    }

    @Override
    public String toString() {
            return value;
        }
    }

您可以使用此课程来处理我在问题中提到的唯一性问题。


更新

但是,由于JFreeChart使用toString()方法为类别创建标签。因此toString()中的UniqueValue实现可能非常奇怪。所以这是另一种尝试。

首先,生成器接口

public interface CategoryLabelGenerator {
    public String generate(Comparable<?> category);
}

然后我为CategoryAxis

创建一个子类
public class CategoryLabelCustomizableCategoryAxis extends CategoryAxis {

    private static final long serialVersionUID = 1L;
    private CategoryLabelGenerator labelGenerator;

    public CategoryLabelCustomizableCategoryAxis(String label) {
        super(label);
    }

    public void setCategoryLabelGenerator(CategoryLabelGenerator generator) {
        this.labelGenerator = generator;
    }

    @Override
    protected TextBlock createLabel(Comparable category, float width, 
        RectangleEdge edge, Graphics2D g2) {
        if (generator == null) {
            return super.createLabel(category, width, edge, g2);
        }
        return TextUtilities.createTextBlock(
            labelGenerator.generate(category),  // generate label for category on the fly
            getTickLabelFont(category), getTickLabelPaint(category), width,
            getMaximumCategoryLabelLines(), new G2TextMeasurer(g2));
    }
}

示例:

JFreeChart chart = makeChart();
CategoryPlot plot = chart.getCategoryPlot();

CategoryAxis axis = new CategoryLabelCustomizableCategoryAxis();
axis.setCategoryLabelGenerator(new MyCategoryLabelGenerator());
plot.setDomainAxis(axis);

这是我自定义类别标签的方式。 (至少对于使用CategoryAxis作为域轴的图表。)