How can I update a JFreeChart's appearance after it's been made visible?
The class ChartPanel
is convenient for this, as it has methods to control the chart's overall appearance, including properties and zoom state. In addition it's also possible to access the chart's components, as shown below. This related example illustrates a JToolBar
of zoom buttons.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
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.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.Year;
import org.jfree.data.xy.XYDataset;
/** @see http://stackoverflow.com/questions/5522575 */
public class ChartPanelDemo {
private static final String title = "Return On Investment";
private ChartPanel chartPanel = createChart();
public ChartPanelDemo() {
JFrame f = new JFrame(title);
f.setTitle(title);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new BorderLayout(0, 5));
f.add(chartPanel, BorderLayout.CENTER);
chartPanel.setMouseWheelEnabled(true);
chartPanel.setHorizontalAxisTrace(true);
chartPanel.setVerticalAxisTrace(true);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
panel.add(createTrace());
panel.add(createDate());
panel.add(createZoom());
f.add(panel, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private JComboBox createTrace() {
final JComboBox trace = new JComboBox();
final String[] traceCmds = {"Enable Trace", "Disable Trace"};
trace.setModel(new DefaultComboBoxModel(traceCmds));
trace.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (traceCmds[0].equals(trace.getSelectedItem())) {
chartPanel.setHorizontalAxisTrace(true);
chartPanel.setVerticalAxisTrace(true);
chartPanel.repaint();
} else {
chartPanel.setHorizontalAxisTrace(false);
chartPanel.setVerticalAxisTrace(false);
chartPanel.repaint();
}
}
});
return trace;
}
private JComboBox createDate() {
final JComboBox date = new JComboBox();
final String[] dateCmds = {"Horizontal Dates", "Vertical Dates"};
date.setModel(new DefaultComboBoxModel(dateCmds));
date.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFreeChart chart = chartPanel.getChart();
XYPlot plot = (XYPlot) chart.getPlot();
DateAxis domain = (DateAxis) plot.getDomainAxis();
if (dateCmds[0].equals(date.getSelectedItem())) {
domain.setVerticalTickLabels(false);
} else {
domain.setVerticalTickLabels(true);
}
}
});
return date;
}
private JButton createZoom() {
final JButton auto = new JButton(new AbstractAction("Auto Zoom") {
@Override
public void actionPerformed(ActionEvent e) {
chartPanel.restoreAutoBounds();
}
});
return auto;
}
private ChartPanel createChart() {
XYDataset roiData = createDataset();
JFreeChart chart = ChartFactory.createTimeSeriesChart(
title, "Date", "Value", roiData, true, true, false);
XYPlot plot = chart.getXYPlot();
XYLineAndShapeRenderer renderer =
(XYLineAndShapeRenderer) plot.getRenderer();
renderer.setBaseShapesVisible(true);
NumberFormat currency = NumberFormat.getCurrencyInstance();
currency.setMaximumFractionDigits(0);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setNumberFormatOverride(currency);
return new ChartPanel(chart);
}
private XYDataset createDataset() {
TimeSeriesCollection tsc = new TimeSeriesCollection();
tsc.addSeries(createSeries("Projected", 200));
tsc.addSeries(createSeries("Actual", 100));
return tsc;
}
private TimeSeries createSeries(String name, double scale) {
TimeSeries series = new TimeSeries(name);
for (int i = 0; i < 6; i++) {
series.add(new Year(2005 + i), Math.pow(2, i) * scale);
}
return series;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ChartPanelDemo cpd = new ChartPanelDemo();
}
});
}
}
How to update a chart in JFreeChart?
ChartPanel
"registers with the chart to receive notification of changes to any component of the chart. The chart is redrawn automatically whenever this notification is received." There are examples here and here.
How can I get my JFree chart to update once its displayed with new Y ranges?
Absent your sscce, it's not clear how your program fails. You should only need validate()
and repaint()
if you add or remove components. You can update your chart dynamically as shown here and here.
Update transparancy of jFreeChart in real time with JSlider
The critical issue is to notify the chart that you've modified "the pie chart that is used to draw the individual pie plots."
chart.fireChartChanged();
Simplified SSCCE:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.math.BigDecimal;
import java.math.BigInteger;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
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.util.TableOrder;
/**
* @see http://stackoverflow.com/a/17370398/230513
* This example is similar to {@link MultiplePieChartDemo1}, but slices the
* dataset by column rather than by row.
*/
public class MultiplePieChart extends JPanel {
private JSlider slider = new JSlider();
private CategoryDataset createDataset() {
BigInteger topSources = new BigInteger("100");
BigInteger notTopSources = new BigInteger("10");
DefaultCategoryDataset dataset = new DefaultCategoryDataset();
dataset.addValue(topSources, "Included Sources", "Sales Quantity");
dataset.addValue(notTopSources, "Not Included Sources", "Sales Quantity");
BigDecimal topSourcesTotal = new BigDecimal("1450.34");
BigDecimal notTopSourcesTotal = new BigDecimal("99.78");
dataset.addValue(topSourcesTotal, "Included Sources", "Sales Total");
dataset.addValue(notTopSourcesTotal, "Not Included Sources", "Sales Total");
return dataset;
}
private JFreeChart createChart() {
final JFreeChart chart = ChartFactory.createMultiplePieChart(
"Sales", createDataset(), TableOrder.BY_COLUMN, true, true, false);
MultiplePiePlot plot = (MultiplePiePlot) chart.getPlot();
JFreeChart subchart = plot.getPieChart();
final PiePlot p = (PiePlot) subchart.getPlot();
p.setForegroundAlpha(0.5f);
slider.setValue((int) (p.getForegroundAlpha() * 100));
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
float value = (float) slider.getValue() / (float) 100;
p.setForegroundAlpha(value);
chart.fireChartChanged();
}
});
return chart;
}
public JPanel createChartPanel() {
JFreeChart chart = createChart();
final ChartPanel chartPanel = new ChartPanel(chart) {
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 400);
}
};
return chartPanel;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MultiplePieChart mpc = new MultiplePieChart();
JFrame frame = new JFrame();
frame.add(mpc.createChartPanel());
frame.add(mpc.slider, BorderLayout.SOUTH);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
jfreechart general issue on the possibility of interactlively modify a displayed curve dragging mouse
JFreeChart
can certainly handle dynamic charts, as shown here; and you can interact in a variety of ways with an existing chart, as shown here.
Addendum: Here's a few more specifics:
The default tooltip generator displays data when you hover over a point, but you can also supply a custom generator.
ChartPanel
implements bothMouseListener
andMouseMotionListener
.The JWS demo is a trove of examples, many interactive. The
crosshair
demos are particularly appealing.
JFreeChart: Preserve zoom position when updating chart
ChartPanel
has methods getScaleX()
and getScaleY()
that could be used to cache the current zoom state for later restoration by one of the zoom methods. There's a related example here.
Update PieChart in JFreeChart
As shown here, you can alter a chart after it's been rendered. In this case, update the chart's data model, PieDataset
, and the listening view will follow; in these related examples, a component's Action
updates a Dataset
. In a MultiplePiePlot
, you can update the appearance of the pie chart view directly, as shown here.
Addendum: Starting from PieChartDemo1
, re-factor the dataset and add a suitable Action
, as shown below.
private static final DefaultPieDataset dataset = createDataset();
…
public PieChartDemo1(String title) {
super(title);
add(createDemoPanel());
add(new JButton(new AbstractAction("Update") {
@Override
public void actionPerformed(ActionEvent e) {
dataset.setValue("Apple", dataset.getValue("Apple").doubleValue() + 1);
}
}), BorderLayout.SOUTH);
}
Related Topics
Using Threads to Make Database Requests
What's the Reason I Can't Create Generic Array Types in Java
Extends Jframe Vs. Creating It Inside the Program
How to Add Blank Page in Digitally Signed Pdf Using Java
Removing Whitespace from Strings in Java
Calculating Days Between Two Dates With Java
How to Split a String by Space
How to Set the Java.Library.Path from Eclipse
Best Way to Parsedouble With Comma as Decimal Separator
Why Can't I Do Assignment Outside a Method
Sorting an Arraylist of Objects Using a Custom Sorting Order
How to Format the Day of the Month to Say "11Th", "21St" or "23Rd" (Ordinal Indicator)
Draw a Line in a Jpanel With Button Click in Java
How Does the "Final" Keyword in Java Work (I Can Still Modify an Object.)
Getting the Name of the Currently Executing Method