【问题标题】:Is it possible to customize label for each category in bar chart?是否可以为条形图中的每个类别自定义标签?
【发布时间】:2012-06-07 11:04:52
【问题描述】:

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

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

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

所以我的问题是:

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

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

【问题讨论】:

    标签: java jfreechart


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,我实现了UniqueValue 作为类别,它为我解决了这个问题:)
    • 这是我如何实现UniqueValue class see my answer
    【解决方案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() 方法为类别创建标签。所以UniqueValue 中的toString() 实现可能很奇怪。所以这是另一个尝试。

    一、生成器接口

    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 作为域轴的图表..)

    【讨论】:

    • 看起来不错。有什么(有用的)方法可以消除toString() 的结果的歧义吗?
    • (我不确定我是否明白你的意思)除非 JFreeChart 将创建类别标签的实现从 toString() 更改为其他方法,否则我想不出好的方法。我也不喜欢toString() 现在的样子:(
    • 嗯...也许我可以覆盖CategoryAxis类中的createLabel方法,所以它不会总是使用toString()来获取类别的文本。
    • 也许是tooltip generator 以获得更具描述性的名称?
    • 我再试一次,这应该是更好的方法。请参阅我的更新答案。
    猜你喜欢
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    相关资源
    最近更新 更多