2

渡されるデータのタイプ (整数対金額対パーセンテージ) に基づいて、グラフの各円グラフにカスタム レンダラーを追加しようとしています。ただし、 a のデータにはPieDatasetキーが 1 つしかないようです (一方、データセットが a として作成されたDefaultCategoryDataset場合、 arowKeyと aがありますcolumnKey)。

下の図で、私が達成しようとしているのは、右側のグラフ ("Sales Total") に金額 ( $ #,##0.00) が表示されることです。

ここに画像の説明を入力

私が試したこと: カスタムレンダラーを作成してデータ型の ENUM を渡そうとしましたが、レンダラー内でどのパイがレンダリングされているかを判断できなかったため、データ型が原因で機能しませんでした:

    static class CustomLabelGenerator implements PieSectionLabelGenerator {
        public String generateSectionLabel(PieDataset dataset, Comparable key) {
            NumberFormat nf;
            // How do you find out which pie is being rendered? "key" relates to Bob, Sally, George, Tom, etc.
            switch (data_type) {
                case currency:
                    nf = new DecimalFormat("$ #,##0.00");
                    break;
                case integer:
                    nf = new DecimalFormat("#,##0");
                    break;
                case percentage:
                    nf = new DecimalFormat("#,##0.00 %");
                    break;
                default:
                    throw new IllegalStateException("Invalid ENUM. This is impossible");
            }
            return nf.format(dataset.getValue(key));
        }
        public AttributedString generateAttributedSectionLabel(
                PieDataset dataset, Comparable key) {
            return null;
        }
    }

これは可能ですか?jFreeChart の複数の円グラフのデモはすべて、同じ画面上のすべての円グラフで対称的なデータ型を示しています。これを 2 つの別々のグラフ/パネルに分ける必要がありますか? だとしたら悲惨だな…

SSCCE は次のとおりです (jFreeChart ライブラリがある場合)。

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.text.AttributedString;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.labels.PieSectionLabelGenerator;
import org.jfree.chart.plot.MultiplePiePlot;
import org.jfree.chart.plot.PiePlot;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.util.TableOrder;

/**
 * This example is similar to {@link MultiplePieChartDemo1}, but slices the
 * dataset by column rather than by row.
 */
public class MultiplePieChart extends JPanel {

    /**
     * Creates a sample dataset.
     *
     * @return A sample dataset.
     */
    private static CategoryDataset createDataset() {
        int bob_quantity = 100;
        int sally_quantity = 115;
        int george_quantity = 112;
        int tom_quantity = 99;
        DefaultCategoryDataset dataset = new DefaultCategoryDataset();
        dataset.addValue(bob_quantity, "Bob", "Sales Quantity");
        dataset.addValue(sally_quantity, "Sally", "Sales Quantity");
        dataset.addValue(george_quantity, "George", "Sales Quantity");
        dataset.addValue(tom_quantity, "Tom", "Sales Quantity");

        double bob_total = 1450.40;
        double sally_total = 1545.12;
        double george_total = 1550.56;
        double tom_total = 1200.90;
        dataset.addValue(bob_total, "Bob", "Sales Total");
        dataset.addValue(sally_total, "Sally", "Sales Total");
        dataset.addValue(george_total, "George", "Sales Total");
        dataset.addValue(tom_total, "Tom", "Sales Total");

        return dataset;
    }

    /**
     * Creates a sample chart with the given dataset.
     *
     * @param dataset  the dataset.
     *
     * @return A sample chart.
     */
    private static JFreeChart createChart(CategoryDataset dataset, String chartTitle, boolean includeLegend, Data_Type data_type) {
        JFreeChart chart = ChartFactory.createMultiplePieChart(
            chartTitle,  // chart title
            dataset,               // dataset
            TableOrder.BY_COLUMN,
            includeLegend,                  // include legend
            true,
            false
        );
        MultiplePiePlot plot = (MultiplePiePlot) chart.getPlot();
        plot.setBackgroundPaint(Color.white);
        plot.setOutlineStroke(new BasicStroke(1.0f));

        JFreeChart subchart = plot.getPieChart();
        PiePlot p = (PiePlot) subchart.getPlot();

        p.setBackgroundPaint(null);
        p.setOutlineStroke(null);
        p.setStartAngle(0);

//        p.setLabelGenerator(new StandardPieSectionLabelGenerator("{0} ({2})",
//                NumberFormat.getNumberInstance(),
//                NumberFormat.getPercentInstance()));
        p.setMaximumLabelWidth(0.20);

        p.setLabelGenerator(new CustomLabelGenerator(data_type));


        return chart;
    }

    /**
     * Creates a panel for the demo (used by SuperDemo.java).
     *
     * @return A panel.
     */
    public static JPanel createPanel(CategoryDataset dataset, Dimension size, String chartTitle, boolean includeLegend, Data_Type data_type) {
        JFreeChart chart = createChart(dataset, chartTitle, includeLegend, data_type);
        ChartPanel panel = new ChartPanel(chart);
        panel.setMouseWheelEnabled(true);
        if(size != null)
            panel.setPreferredSize(size);
        return panel;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        JPanel panel = createPanel(createDataset(), new Dimension(800, 500), "Sales", true, Data_Type.integer);
        frame.add(panel);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
    }


    enum Data_Type {
        integer,
        percentage,
        currency
    }

    static class CustomLabelGenerator implements PieSectionLabelGenerator {


        private final Data_Type data_type;

        public CustomLabelGenerator(Data_Type data_type) {
            this.data_type = data_type;
        }

        public String generateSectionLabel(PieDataset dataset, Comparable key) {
            NumberFormat nf;
            switch (data_type) {
                case currency:
                    nf = new DecimalFormat("$ #,##0.00");
                    break;
                case integer:
                    nf = new DecimalFormat("#,##0");
                    break;
                case percentage:
                    nf = new DecimalFormat("#,##0.00 %");
                    break;
                default:
                    throw new IllegalStateException("Invalid ENUM. This is impossible");
            }
            return nf.format(dataset.getValue(key));
        }

        public AttributedString generateAttributedSectionLabel(
                PieDataset dataset, Comparable key) {
            return null;
        }

    }
}
4

1 に答える 1

3

これは少しぎこちなく感じますが、うまくいくようです。私がやっていることは、PieDataset渡された toを取得して、generateSectionLabelそれが元のどの列にあるかを把握することですCategoryDatasetCategoryToPieDataset#equals(PieDataset)すべてのキーと値を比較して一致するかどうかを確認しているのは私の理解です。このアプローチは、列挙型をまったく使用せず、生成対象の列を確認するだけです。

static class CustomLabelGenerator implements PieSectionLabelGenerator {
  private final CategoryDataset catDataset;

  public CustomLabelGenerator(CategoryDataset catDataset) {
    this.catDataset = catDataset;
  }

  public String generateSectionLabel(PieDataset dataset, Comparable key) {
    int column = 0;
    for (int c = 0; c < catDataset.getColumnCount(); c++) {
      CategoryToPieDataset categoryToPieDataset = 
          new CategoryToPieDataset(catDataset, TableOrder.BY_COLUMN, c);
      if (categoryToPieDataset.equals(dataset)) {
        column = c;
        break;
      }
    }
    NumberFormat nf;
    switch (column) {
      case 0: // the 'Sales Quantity' column
        nf = new DecimalFormat("#,##0");
        break;
      case 1: // the 'Sales Total' column
        nf = new DecimalFormat("$ #,##0.00");
        break;
      default:
        throw new IllegalStateException("Invalid column. This is impossible");
    }
    return nf.format(dataset.getValue(key));
  }
}

結果: 結果

JFree API に詳しい人がより良い解決策を持っていない限り、単一の円グラフを作成してX_AXIS BoxLayout.

于 2013-06-03T20:48:17.553 に答える