2

I want to put a chart inside a specific panel in a GUI using JFreeChart. I have 2 java files (one with the GUI, and another that creates the graph) and would like , if possible, to keep it this way.

In the main GUI I have a panel called panelGraph:

    JPanel panelGraph = new JPanel();
    panelGraph.setBounds(220, 64, 329, 250);
    panelMain.add(panelGraph); //it is inside the main panel
    panelGraph.setLayout(null);

And I also have a button that triggers the appearance of the graph:

    Button btnGetGraph = new JButton("Draw Graph");
    btnGetGraph.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {

            XYLineChart_AWT.runGraph("Cenas", "Titulo", "XLABEL", "YLABEL", panelGraph);

        }
    });
    btnGetGraph.setFont(new Font("Tahoma", Font.BOLD, 13));
    btnGetGraph.setBounds(323, 327, 128, 34);
    panelMain.add(btnGetGraph);

And as follows, is the java file that creates the graph:

  public class XYLineChart_AWT extends JFrame {
  public XYLineChart_AWT( String applicationTitle, String chartTitle, String xLabel, String yLabel, JPanel panel) {

  JFreeChart xylineChart = ChartFactory.createXYLineChart(
     chartTitle ,
     xLabel ,
     yLabel ,
     createDataset() ,
     PlotOrientation.VERTICAL ,
     true , false , false);

  ChartPanel chartPanel = new ChartPanel( xylineChart );
  chartPanel.setPreferredSize( panel.getSize() );


  final XYPlot plot = xylineChart.getXYPlot( );
  plot.setBackgroundPaint(new Color(240, 240, 240));
  XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true,false);
  renderer.setSeriesPaint( 0 , Color.BLACK );
  renderer.setSeriesStroke( 0 , new BasicStroke( 4.0f ) );
  plot.setRenderer( renderer );
  setContentPane(chartPanel);
  panel.add(chartPanel);
  }

private XYDataset createDataset( ){

  final XYSeries seno = new XYSeries ("Sin");
  for(double i=0;i<=1440;i++){
      double temp=Math.sin(i*((2*Math.PI)/640) + Math.PI) + 1;
      seno.add(i/60, temp);
  }


  final XYSeriesCollection dataset = new XYSeriesCollection( );          
  dataset.addSeries(seno);
  return dataset;
}

public static void runGraph(String appTitle, String chartTitle, String xLabel, String yLabel, JPanel panel) {
  XYLineChart_AWT chart = new XYLineChart_AWT(appTitle, chartTitle, xLabel, yLabel, panel);

  chart.pack();
  chart.setVisible(true);
  panel.setVisible(true);

 }
}

This creates the graph and puts it into the specified panel (that I send through the method runGraph()). However, it creates a 2nd JFrame ( I know i made chart.setVisible(true) and I can just put it to false) that I don't want to be created outside of the panel I send.

Is there any way to implement this that does not create that extra jFrame?

P.S.: Another question: the setBackgroundPaint() method changes the back of where the graph is shown. However the parts where the title and legend are don't change. How can I change those parts?

Thank you for your help,

Nhekas

dgteixeira
  • 61
  • 9

2 Answers2

2

Instead of using the XYLineChartAWT constructor to instantiate a ChartPanel, make runGraph() a factory method that returns a JFreeChart for use in your main GUI's ChartPanel. Use the chart panel method setChart(), which will update your panel automatically. To change the chart panel's default size, override getPreferredSize() as shown here.

image

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see https://stackoverflow.com/a/36757609/230513
 */
public class Test {

    private void display() {
        JFrame f = new JFrame("Test");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final ChartPanel chartPanel = new ChartPanel(null);
        f.add(chartPanel);
        f.add(new JButton(new AbstractAction("Draw Graph") {
            @Override
            public void actionPerformed(ActionEvent e) {
                chartPanel.setChart(
                    new XYLineChartAWT().runGraph("Title", "X", "Y"));
            }
        }), BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Test()::display);
    }
}

public class XYLineChartAWT {

    public JFreeChart runGraph(String chartTitle, String xLabel, String yLabel) {
        JFreeChart xylineChart = ChartFactory.createXYLineChart(
            chartTitle,
            xLabel,
            yLabel,
            createDataset(),
            PlotOrientation.VERTICAL,
            true, false, false);
        final XYPlot plot = xylineChart.getXYPlot();
        plot.setBackgroundPaint(new Color(240, 240, 240));
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false);
        renderer.setSeriesPaint(0, Color.BLACK);
        renderer.setSeriesStroke(0, new BasicStroke(4.0f));
        plot.setRenderer(renderer);
        return xylineChart;
    }

    private XYDataset createDataset() {
        final XYSeries seno = new XYSeries("Sin");
        for (double i = 0; i <= 1440; i++) {
            double temp = Math.sin(i * ((2 * Math.PI) / 640) + Math.PI) + 1;
            seno.add(i / 60, temp);
        }
        final XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(seno);
        return dataset;
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Thanks for your input. I will try this later today and I will come back with a proper reply. Thanks for the answer! – dgteixeira Apr 21 '16 at 11:27
  • In order for it to work properly I had do use .setBounds() method on the chartPanel created for the graph. However, for what I read online, this is not the best pratice. I am supposed to use LayoutManagers, right? Which one do you recommend to use? Thanks in advance – dgteixeira Apr 26 '16 at 13:58
  • @Nhekas: I agree about avoiding `setBounds()`. The default layout of `JFrame` is `BorderLayout` and the default destination is `CENTER`, implicit in the above example; `GridLayout`, seen [here](http://stackoverflow.com/a/10277372/230513), also allows the chart to adjust as the frame is resized. – trashgod Apr 26 '16 at 14:25
  • Ok, I will try that Layout. Another non-related question: when creating the main frame, how should I create it ? If i use pack() method, even if I have multiple components, it will start really small. Is it because currently is set as a null (absolute) layout? – dgteixeira Apr 26 '16 at 14:48
  • Right; also override `getPreferredSize()` so `pack()` will know how big the panel should be. – trashgod Apr 26 '16 at 15:03
1

I want to suggest use Nice Application 1 the Jfree modified jar can download from NiceApplication1.BlogSpot.Com. Go to the blog and Download new Nice Application 1 Home Stupendous, then after extract, the folder go to the dist folder and open the Java Jar Nice Application 1, so you will get a modified jar jfree_NiceApplication1 with a notepad file about how can use that jar.

A pie chart example is available.

After jar only need to type method-

String ao1 = a1.getText(); String ao2 = a2.getText();

DefaultPieDataset pieDataset = new DefaultPieDataset();

    pieDataset.setValue("earn", new Double(ao1));
    pieDataset.setValue("Allbilltotal", new Double(ao2));

//Note pieDataset & ch will be your variable.

JFreeChart ch = ChartFactory.createPieChart3D("Test", pieDataset, true, true, true);

    PiePlot3D p = (PiePlot3D) ch.getPlot();

// import org.jfree.chart.Nice_Application_1_JPanel;

    Nice_Application_1_JPanel pant = new Nice_Application_1_JPanel(pieDataset);  
    pieDataset = pant.pieDataset;
    pant.PanelApplication1 = jPanel;   
    pant.size = new java.awt.Dimension(200, 200);
    pant.Nice_Application1(ch);

StandardChartTheme theme = new StandardChartTheme(ch.toString());

theme.setTitlePaint( Color.decode( "#4572a7" ) );
theme.setRangeGridlinePaint( Color.decode("#C0C0C0"));
theme.setPlotBackgroundPaint( Color.blue );
theme.setChartBackgroundPaint( Color.BLACK );
theme.setGridBandPaint( Color.red );
theme.setBarPainter(new StandardBarPainter());
theme.setAxisLabelPaint( Color.decode("#666666")  );

theme.apply( ch );


For line chart also can type the same, the place of the Chart panel type only- // import org.jfree.chart.Nice_Application_1_JPanel;

    Nice_Application_1_JPanel pant = new Nice_Application_1_JPanel(pieDataset);  
    pieDataset = pant.pieDataset;
    pant.PanelApplication1 = jPanel;   
    pant.size = new java.awt.Dimension(200, 200);
    pant.Nice_Application1(ch);

Alan
  • 9
  • 4