使用JFreeChart生成多饼图时,如何设置其布局,如将生成的多个饼图设置成一行或多行,行数由自己控制,使用
ChartFactory.createMultiplePieChart(
            "Multiple Pie Chart",  // chart title
            dataset,               // dataset
            TableOrder.BY_ROW,
            true,                  // include legend
            true,
            false
); 
可以生成多个饼图,但是不知如何控制其布局,如何将饼图显示为一行,请高手赐教,谢谢!

解决方案 »

  1.   

      createMultiplePieChart这个方法生成的多个图是可以布局的,但是他是你dataset.addValue()有几个他就生成几个图。而且都是一样的。
      用java图形用户界面来做那就用java的布局管理器类来做如下:
         JPanel panel = new JPanel(new GridLayout(2, 2));
        //new GridLayout(2, 2)网格型的布局处理器,就是把容器被分成大小相等的矩形,一个矩形中放置一个组件。这是个2行*2列的布局
         DefaultCategoryDataset dataset=new DefaultCategoryDataset();
        dataset.addValue(23.3, "Section 1", "Section");
        dataset.addValue(56.5, "Section 2", "Section");
        dataset.addValue(43.3, "Section 3", "Section");
        dataset.addValue(11.1, "Section 4", "Section");
        JFreeChart chart1 = ChartFactory.createMultiplePieChart("Multiple Pie Chart", dataset,TableOrder.BY_ROW, 
                            true,true, false ); 
        panel.add(new ChartPanel(chart1));
        panel.setPreferredSize(new Dimension(800, 600));//设置整个画布的大小
      这样你生成的图就会是2行*2列的,要其他的只要改new GridLayout(2, 2)这个就好了。还有其他多种布局方式,如FlowLayout,BorderLayout
      但是不是很好用,会比较复杂点。
      这要看你是用什么方法做饼图了。
      
      
      如果是通过jfreechart+cewolf 那就不懂了。
      如果想要有多个不同的图。
      JPanel panel = new JPanel(new GridLayout(2, 3));
      DefaultCategoryDataset dataset=new DefaultCategoryDataset();
      dataset.setValue("Section 1", 23.3);
      dataset.setValue("Section 2", 56.5);
      dataset.setValue("Section 3", 43.3);
      dataset.setValue("Section 4", 11.1);
      JFreeChart chart1 = ChartFactory.createPieChart("Chart 1", dataset, 
                    false, false, false);
      JFreeChart chart2 = ChartFactory.createPieChart("Chart 2", dataset, 
                    false, false, false);
      JFreeChart chart3 = ChartFactory.createPieChart("Chart 2", dataset, 
                    false, false, false);
      JFreeChart chart4 = ChartFactory.createPieChart("Chart 2", dataset, 
                    false, false, false);
      panel.add(new ChartPanel(chart1));
      panel.add(new ChartPanel(chart2));
      panel.add(new ChartPanel(chart3));
      panel.add(new ChartPanel(chart4));  panel.setPreferredSize(new Dimension(800, 600));
                    
      

  2.   

    谢谢楼上兄弟答复,不知道你自己有没有测试过你的代码是否能达到效果,运行你上面的代码好像没有达到效果,不知道是否是我的方法有问题,还是……
    分析你的代码,个人理解,在使用
    ChartFactory.createMultiplePieChart("Multiple Pie Chart", dataset,TableOrder.BY_ROW, true, true, false );
    就已经画出饼图并布局好了,要修改布局,可能要在饼图创建之前修改,而你的方法是在饼图完全生成后才在布局,应该是没有效果的吧。
      

  3.   

    我用eclipse测试过了,是ok的。我有点不明白你要生成多个完全一样的图干什么呢?你是用什么开发的?jsp还是用java的图形用户界面?
      

  4.   

    可以把你的源码发一份给我吗?我需要画的是多个饼图(数据不一样),而且饼图要排列在同一行里,我们用Tapestry框架,开发组件用的。
      

  5.   

    public class PieChartDemo1 extends ApplicationFrame {    /**
         * Creates a new demo instance.
         * 
         * @param title  the frame title.
         */
        public PieChartDemo1(String title) {
            super(title);
            setContentPane(createDemoPanel());
        }    /**
         * Creates a panel for the demo (used by SuperDemo.java).
         * 
         * @return A panel.
         */
        public static JPanel createDemoPanel() {
            //-----------这是相同数据源的多个图的布局----2行3列
         JPanel panel = new JPanel(new GridLayout(2, 3));
            DefaultCategoryDataset dataset=new DefaultCategoryDataset();
            
            dataset.addValue(23.3, "Section 1", "Section");
            dataset.addValue(56.5, "Section 2", "Section");
            dataset.addValue(43.3, "Section 3", "Section");
            dataset.addValue(11.1, "Section 4", "Section");
            dataset.addValue(11.1, "Section 5", "Section");
            
            JFreeChart chart1 = ChartFactory.createMultiplePieChart("Multiple Pie Chart", dataset,TableOrder.BY_ROW, true,true, false );         chart1.addSubtitle(new TextTitle("setCircular(true);", 
                    new Font("Dialog", Font.PLAIN, 12)));
            
            panel.add(new ChartPanel(chart1));
            panel.setPreferredSize(new Dimension(800, 600));
            return panel;
           
        }
        
        /**
         * The starting point for the demo.
         * 
         * @param args  ignored.
         */
        public static void main(String[] args) {
            PieChartDemo5 demo = new PieChartDemo5("Pie Chart Demo 5");
            demo.pack();
            int j=i;
            RefineryUtilities.centerFrameOnScreen(demo);
            demo.setVisible(true);
        }}
      

  6.   

            PieChartDemo5 demo = new PieChartDemo5("Pie Chart Demo 5"); 要改为
             PieChartDemo1 demo = new PieChartDemo1("Pie Chart Demo 5"); 
     
       
      

  7.   

    public class PieChartDemo2 extends ApplicationFrame {    /**
         * Creates a new demo instance.
         * 
         * @param title  the frame title.
         */
    static int i=0;
        public PieChartDemo2(String title) {
            super(title);
            setContentPane(createDemoPanel());
        }    /**
         * Creates a panel for the demo (used by SuperDemo.java).
         * 
         * @return A panel.
         */
        public static JPanel createDemoPanel() {
         //     -------多个不同数据源的布局----你要都在一行可以设成1行多列。比如1*3
            //------要多个不同数据的图,,你只要定义多个DefaultPieDataset取得多个不同的数据。然后填充进去就好了
         JPanel panel = new JPanel(new GridLayout(1, 3));
            
            DefaultPieDataset dataset1 = new DefaultPieDataset();
            dataset1.setValue("Section 1", 23.3);
            dataset1.setValue("Section 2", 56.5);
            dataset1.setValue("Section 3", 43.3);
            dataset1.setValue("Section 4", 11.1);        JFreeChart chart1 = ChartFactory.createPieChart("Chart 2", dataset1, 
                    false, false, false);
            chart1.addSubtitle(new TextTitle("setCircular(false);", 
                    new Font("Dialog", Font.PLAIN, 12)));//设置标题
            PiePlot plot2 = (PiePlot) chart1.getPlot();
            plot2.setCircular(false);//设置饼图是否为正圆。false饼图会不够圆,有点扁。
            
            DefaultPieDataset dataset2 = new DefaultPieDataset();
            dataset2.setValue("demo 1", 23.3);
            dataset2.setValue("demo 2", 56.5);
            dataset2.setValue("demo 3", 43.3);
            dataset2.setValue("demo 4", 11.1);
            
            JFreeChart chart2 = ChartFactory.createPieChart3D("Chart 3", dataset2, 
                    false, false, false);
            chart2.addSubtitle(new TextTitle("setCircular(true);", 
                    new Font("Dialog", Font.PLAIN, 12)));
            PiePlot3D plot3 = (PiePlot3D) chart2.getPlot();
            plot3.setForegroundAlpha(0.6f);
            plot3.setCircular(true);        panel.add(new ChartPanel(chart1));
            panel.add(new ChartPanel(chart2));
            panel.setPreferredSize(new Dimension(800, 600));
            return panel;
           
        }
        
        /**
         * The starting point for the demo.
         * 
         * @param args  ignored.
         */
        public static void main(String[] args) {
            PieChartDemo2 demo = new PieChartDemo2("Pie Chart Demo 2");
            demo.pack();
            int j=i;
            RefineryUtilities.centerFrameOnScreen(demo);
            demo.setVisible(true);
        }}
      

  8.   

    谢谢兄弟答复,对于你的第一种方案 相同数据源的多个图的布局 通过new GridLayout(2, 3)来设置布局并没有效果,你的代码中有五个饼图,如果设置为new GridLayout(1, 5),并不可以把五个饼图排成一行。对于第二种方案,其实之前就有尝试过,但是我们的项目比较特殊,可能会有很多个饼图(上百个),如果每个饼图都生成一个实例的话,那会很耗费资源,本来Tapestry的效率就有问题,所以就没有考虑了。不知道兄弟是否还有其它方案,我更倾向与 相同数据源的多个图的布局,只是还没有找到实现方案,这两天在看JFreeChart的源码,但还没有找到它画多饼图时的布局方法。
      

  9.   

      第一种我试了啊。ok的啊。那我也不知道怎么回事了。这个布局其实是java的布局。
      那是因为整个图的大小是有限的。你怎么可能在一行放那么多图呢?而且如你所说上百个图怎么可能放在一行上?jfreechart这东西本来就是一个数据源对应一个图的。估计你的数据源的个数是动态的这比较麻烦。能力有限帮不了你啦兄弟。jfreechart还有很多高级应该偶也不会,只是网上很少这东西的高级应该。而jfreechart的那个开发指南是收费的。好像有点贵。(*^__^*) 嘻嘻……。
      

  10.   

    谢谢兄弟热情帮助,问题已解决。
    今天我跟了一下JFreeChart的源码,发现有一个draw方法控制了布局,通过修改该方法可以将同一数据源的所有饼图放在同一行中。
    在类 MultiplePiePlot 中约341行左右有一方法draw,JFreeChart通过该方法生成饼图,在该方法中有两个参数 displayCols 和 displayRows 一个是控制列数一个是控制行数,我将列数修改为饼图个数,行数改为1,就可以实现多个饼图放在同一行中,方法如下。
        public void draw(Graphics2D g2, 
                         Rectangle2D area
                         Point2D anchor,
                         PlotState parentState,
                         PlotRenderingInfo info) {
            
           
            // adjust the drawing area for the plot insets (if any)...
            RectangleInsets insets = getInsets();
            insets.trim(area);
            drawBackground(g2, area);
            drawOutline(g2, area);
            
            // check that there is some data to display...
            if (DatasetUtilities.isEmptyOrNull(this.dataset)) {
                drawNoDataMessage(g2, area);
                return;
            }        int pieCount = 0;
            if (this.dataExtractOrder == TableOrder.BY_ROW) {
                pieCount = this.dataset.getRowCount();
            }
            else {
                pieCount = this.dataset.getColumnCount();
            }
            
            //Begin modify by dofare 在一行中显示多个饼图
            /*
            // the columns variable is always >= rows
            int displayCols = (int) Math.ceil(Math.sqrt(pieCount));
            int displayRows 
                = (int) Math.ceil((double) pieCount / (double) displayCols);        // swap rows and columns to match plotArea shape
            if (displayCols > displayRows && area.getWidth() < area.getHeight()) {
                int temp = displayCols;
                displayCols = displayRows;
                displayRows = temp;
            }
            */
            int displayCols = pieCount;
            int displayRows = 1;
            //End modify by dofare 在一行中显示多个饼图        prefetchSectionPaints();
            
            int x = (int) area.getX();
            int y = (int) area.getY();
            int width = ((int) area.getWidth()) / displayCols;
            int height = ((int) area.getHeight()) / displayRows;
            int row = 0;
            int column = 0;
            int diff = (displayRows * displayCols) - pieCount;
            int xoffset = 0;
            Rectangle rect = new Rectangle();        for (int pieIndex = 0; pieIndex < pieCount; pieIndex++) {
                rect.setBounds(x + xoffset + (width * column), y + (height * row), 
                        width, height);            String title = null;
                if (this.dataExtractOrder == TableOrder.BY_ROW) {
                    title = this.dataset.getRowKey(pieIndex).toString();
                }
                else {
                    title = this.dataset.getColumnKey(pieIndex).toString();
                }
                this.pieChart.setTitle(title);
                
                PieDataset piedataset = null;
                PieDataset dd = new CategoryToPieDataset(this.dataset, 
                        this.dataExtractOrder, pieIndex);
                if (this.limit > 0.0) {
                    piedataset = DatasetUtilities.createConsolidatedPieDataset(
                            dd, this.aggregatedItemsKey, this.limit);
                }
                else {
                    piedataset = dd;
                }
                PiePlot piePlot = (PiePlot) this.pieChart.getPlot();
                piePlot.setDataset(piedataset);
                piePlot.setPieIndex(pieIndex);
                
                // update the section colors to match the global colors...
                for (int i = 0; i < piedataset.getItemCount(); i++) {
                    Comparable key = piedataset.getKey(i);
                    Paint p;
                    if (key.equals(this.aggregatedItemsKey)) {
                        p = this.aggregatedItemsPaint;
                    }
                    else {
                        p = (Paint) this.sectionPaints.get(key);
                    }
                    piePlot.setSectionPaint(key, p);
                }
                
                ChartRenderingInfo subinfo = null;
                if (info != null) {
                    subinfo = new ChartRenderingInfo();
                }
                this.pieChart.draw(g2, rect, subinfo);
                if (info != null) {
                    info.getOwner().getEntityCollection().addAll(
                            subinfo.getEntityCollection());
                    info.addSubplotInfo(subinfo.getPlotInfo());
                }
                
                ++column;
                if (column == displayCols) {
                    column = 0;
                    ++row;                if (row == displayRows - 1 && diff != 0) {
                        xoffset = (diff * width) / 2;
                    }
                }
            }    }
      

  11.   

    学习了。谢谢楼主。要改类比较麻烦。要是能设置displayCols和displayRows 这2个值就好了。
      

  12.   

    那请问就是怎么在jsp中实现?java直接运行就行,可是jsp怎么把它保存为图片输出。