1

I have been experimenting with JFreeChart for an upcoming project and looking at the tutorials they seem to be pretty straight forward. I created a simple little program that asks for some data and display a 3D pie chart. It works but when displaying the chart in the panel it only partially shows the chart. If you click inside the panel it will then grow to the size of the display panel. I've tried setting various setPreferredSize() at different places but none of it seems to work. What am I missing?

import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import java.awt.Rectangle;
import javax.swing.JPanel;
import javax.swing.border.EtchedBorder;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JLabel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.JButton;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.util.Rotation;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import net.miginfocom.swing.MigLayout;


@SuppressWarnings("serial")
public class mWindow extends JFrame{

private JPanel pnlDisplay;
private JPanel panel;
private JLabel label_1;
private JLabel label_2;
private JSpinner spinner;
private JButton button;


/**
 *  Window Constructor
 */
private mWindow(){
    setBounds(new Rectangle(0, 0, 600, 500));
    getContentPane().setLayout(new MigLayout("", "[200px:200.00][564px,grow]", "[120px:120.00][308px,grow]"));

    panel = new JPanel();
    panel.setLayout(null);
    panel.setBorder(new EtchedBorder(EtchedBorder.RAISED, null, null));
    getContentPane().add(panel, "cell 0 0,grow");

    label_1 = new JLabel("Control Panel");
    label_1.setBounds(10, 10, 100, 20);
    panel.add(label_1);

    label_2 = new JLabel("Number of Values");
    label_2.setBounds(10, 40, 100, 20);
    panel.add(label_2);

    spinner = new JSpinner();
    spinner.setBounds(120, 40, 40, 20);
    panel.add(spinner);

    button = new JButton("Create Pie Chart");
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            createPieChart();
        }
    });
    button.setBounds(10, 70, 150, 40);
    panel.add(button);

    pnlDisplay = new JPanel();
    pnlDisplay.setBorder(new EtchedBorder(EtchedBorder.RAISED, null, null));
    getContentPane().add(pnlDisplay, "cell 0 1 2 1,grow");
    pnlDisplay.setLayout(null);

}

private void createPieChart(){

    //  create the data set
    //  create the chart
    //  put chart in a panel
    //  set default configuration for panel
    //  add panel to our displayPanel

    int numVal = (int) spinner.getValue();
    JTextField label = new JTextField();
    JTextField value = new JTextField();        
    DefaultPieDataset dds = new DefaultPieDataset();

    final JComponent[] fieldInput = new JComponent[]{
            new JLabel("Label Name"), label,
            new JLabel("Value"), value
    };

    for(int index = 0; index < numVal; index++){
        // Display a dialog asking for the Information Needed to add a job
        int n = JOptionPane.showConfirmDialog(
                this, 
                fieldInput, 
                "Create Data Set " + (index+1), 
                JOptionPane.PLAIN_MESSAGE
        ); 

        if(n < 0){
            JOptionPane.showMessageDialog(this, "No Data Set has been created", 
                    "Data Set Add Canceled ", JOptionPane.ERROR_MESSAGE);
            return;
        } 

        String Label = label.getText();
        int Value = Integer.parseInt(value.getText());
        dds.setValue(Label, Value);
        label.setText("");
        value.setText("");
    }

    // Data set ready ~ create the chart
    JFreeChart chart = ChartFactory.createPieChart3D("Our Pie Chart",          // chart title
            dds,                // data set
            true,               // include legend
            true,               // enable tool tips
            false);             // use urls

    PiePlot3D plot = (PiePlot3D) chart.getPlot();
    plot.setStartAngle(290);                        // angel of first data set
    plot.setDirection(Rotation.CLOCKWISE);          // rotation of chart
    plot.setForegroundAlpha(0.2f);                  // set alpha transparency

    // create a panel to track chart changes and set it's default size
    final ChartPanel chartPanel = new ChartPanel(chart);
    chartPanel.setPreferredSize(pnlDisplay.getSize());


    chartPanel.setBounds(10,10,pnlDisplay.getWidth()-20,pnlDisplay.getHeight()-20);

    // add our chart to our display panel
    pnlDisplay.add(chartPanel);
    pnlDisplay.validate();

}

/**
 *  Initializes and Show the GUI
 */
private static void InitalizeAndShowGUI(){
    mWindow mainWindow = new mWindow();
    mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    mainWindow.setTitle("Chart Demo v0.1");
    Dimension windowSize = new Dimension(600,700);
    mainWindow.setMinimumSize(windowSize);
    mainWindow.setLocation(100, 100);
    mainWindow.pack();
    mainWindow.setVisible(true);
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                InitalizeAndShowGUI();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}
}
jbolt
  • 688
  • 3
  • 16
  • 37

1 Answers1

3

After adding the new chart component, you need to repaint it to make it appear fully:

chartPanel.repaint();
Reimeus
  • 158,255
  • 15
  • 216
  • 276
  • I was just coming back to comment on my original. Yes you are correct repaint() takes care of painting the panel once it has been updated. I am assuming that validate() or revalidate() updates the model while repaint updates the display. Would this be a correct assumption? – jbolt Sep 09 '12 at 22:28
  • Well normlly you wouldnt have to worry about repainting here but as `pnlDisplay` has a null layout, you have to manage the repaint. re/validate() manages the layout of components so dont help you here in this case. – Reimeus Sep 09 '12 at 22:33
  • Thanks I will keep that in mind when working with null layouts. – jbolt Sep 09 '12 at 22:43