3

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

条形图示例

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

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

所以我的问题是:

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

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

4

2 回答 2

4

答案取决于您选择如何CategoryDataset实现KeyedValues2D接口。接口期望键是唯一的,而默认实现,DefaultKeyedValues2D要求键是Comparable不可变的。

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

于 2012-06-07T16:44:26.080 回答
2

This is how I implement 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;
        }
    }

You can use this class to deal with the uniqueness issue I mentioned in questions.


UPDATE

However, since JFreeChart use toString() method to create the label for categories. So the toString() implementation in UniqueValue can be pretty weird. So here is another attempt.

First, a generator interface

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

then I make a subclass for 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));
    }
}

example :

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

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

This is how I customize category label. (At least for chart that use CategoryAxis as domain axis..)

于 2012-06-08T02:35:31.427 回答