How to Update a Jfreechart'S Appearance After It's Been Made Visible

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.

ChartPanelDemo

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(); 

image

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:

  1. The default tooltip generator displays data when you hover over a point, but you can also supply a custom generator.

  2. ChartPanel implements both MouseListener and MouseMotionListener.

  3. 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);
}

Sample Image



Related Topics



Leave a reply



Submit