I have this line chart and want to make it a bar chart, but I'm new to Java and am not knowing if it possible since the x-axis is TimeSeries. This is the code I have that visualizes the line chart:
public class Time {
private static Time INSTANCE;
public static boolean isInitialized = false;
private Marker marker;
private Long markerStart;
private Long markerEnd;
private XYPlot plot;
long last_lowerBound;
long last_upperBound;
#Inject
public Time() {
}
Composite comp;
TimeSeriesCollection dataset;
ChartPanel panel;
JFreeChart chart;
protected Point endPoint;
#PostConstruct
public void postConstruct(Composite parent) {
comp = new Composite(parent, SWT.NONE | SWT.EMBEDDED);
Frame frame = SWT_AWT.new_Frame(comp);
JApplet rootContainer = new JApplet();
TimeSeries series = new TimeSeries("Timeline");
dataset = new TimeSeriesCollection();
String plotTitle = "";
String xaxis = "Time";
String yaxis = "Docs";
PlotOrientation orientation = PlotOrientation.VERTICAL;
boolean show = false;
boolean toolTips = true;
boolean urls = false;
chart = ChartFactory.createTimeSeriesChart(plotTitle, xaxis, yaxis, dataset, show, toolTips, urls );
// get a reference to the plot for further customisation...
plot = chart.getXYPlot();
plot.setBackgroundPaint(Color.white);
plot.setDomainGridlinePaint(Color.gray);
plot.setRangeGridlinePaint(Color.gray);
plot.setOutlinePaint(Color.white);
plot.getRangeAxis().setLabel("");
plot.getDomainAxis().setLabel("");
ValueAxis y_axis = plot.getRangeAxis(); // Y
ValueAxis x_axis = plot.getDomainAxis(); // X
Font font = new Font("Veranda", Font.PLAIN, 12);
y_axis.setTickLabelFont(font);
x_axis.setTickLabelFont(font);
x_axis.setTickLabelPaint(Color.black);
y_axis.setTickLabelPaint(Color.black);
plot.getDomainAxis().setAxisLineVisible(false);
final XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
// renderer.setSeriesLinesVisible(0, false);
renderer.setSeriesShapesVisible(0, false);
plot.setRenderer(renderer);
Should I only update this line: chart = ChartFactory.createTimeSeriesChart(plotTitle, xaxis, yaxis, dataset, show, toolTips, urls ); or I should change it completely?
I tried changing this part like this but it doesn't show anything:
dataset = new TimeSeriesCollection();
String plotTitle = "";
String xaxis = "Time";
String yaxis = "Docs";
PlotOrientation orientation = PlotOrientation.VERTICAL;
boolean show = false;
boolean toolTips = true;
boolean urls = false;
chart = ChartFactory.createBarChart(plotTitle, xaxis, yaxis, (CategoryDataset) dataset, orientation, show, toolTips, urls);
chart.setBackgroundPaint(null);
chart.setBackgroundImageAlpha(0.0f);
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setRangeGridlinesVisible(false);
plot.setDomainGridlinesVisible(false);
plot.setOutlineVisible(false);
plot.setRangeZeroBaselineVisible(false);
plot.setDomainGridlinesVisible(false);
plot.setBackgroundPaint(COLOR_INVISIBLE);
plot.setBackgroundImageAlpha(0.0f);
BarRenderer renderer = (BarRenderer) plot.getRenderer();
renderer.setSeriesPaint(0, AttributeGuiTools.getColorForValueType(Ontology.NOMINAL));
renderer.setBarPainter(new StandardBarPainter());
renderer.setDrawBarOutline(true);
renderer.setShadowVisible(false); } }
Any help would be highly appreciated!
Given a suitable XYDataset, such as IntervalXYDataset, you can replace ChartFactory.createTimeSeriesChart() with ChartFactory.createXYBarChart(), which provides for an optional DateAxis. The example below uses the same dataset to create both charts.
IntervalXYDataset dataset = createDataset();
f.add(createPanel(ChartFactory.createXYBarChart("Data", "Time", true, "Value", dataset)));
f.add(createPanel(ChartFactory.createTimeSeriesChart("Data", "Time", "Value", dataset)));
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.swing.JFrame;
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.DateTickMarkPosition;
import org.jfree.chart.axis.DateTickUnit;
import org.jfree.chart.axis.DateTickUnitType;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.time.Year;
import org.jfree.data.xy.IntervalXYDataset;
/**
* #see https://stackoverflow.com/a/54362133/230513
* #see https://stackoverflow.com/a/42612723/230513
*/
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(new Test()::display);
}
private void display() {
JFrame f = new JFrame("Data");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setLayout(new GridLayout(0, 1));
IntervalXYDataset dataset = createDataset();
f.add(createPanel(ChartFactory.createXYBarChart("Data", "Time", true, "Value", dataset)));
f.add(createPanel(ChartFactory.createTimeSeriesChart("Data", "Time", "Value", dataset)));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private ChartPanel createPanel(JFreeChart chart) {
final XYPlot plot = chart.getXYPlot();
final DateAxis domainAxis = (DateAxis) plot.getDomainAxis();
domainAxis.setTickUnit(new DateTickUnit(DateTickUnitType.YEAR, 1));
domainAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
domainAxis.setDateFormatOverride(new SimpleDateFormat("yyyy"));
return new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 250);
}
};
}
private IntervalXYDataset createDataset() {
TimeSeries series = new TimeSeries("Value");
Calendar c = Calendar.getInstance();
for (int i = 0; i < 7; i++) {
series.add(new Year(c.getTime()), i + 1);
c.add(Calendar.YEAR, 1);
}
return new TimeSeriesCollection(series);
}
}
Related
I have a class that extends JPanel for JFreeChart. Inside of setMean(), I tried updating values of dataset or just the Function2D, but nothing changes on the graph even with repaint().
public class JFreeChartPanel extends JPanel {
Function2D normal = new NormalDistributionFunction2D(0.0, 3.0);
XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal");
double mean = 0.0, std = 1.0;
public double getMean() {
return mean;
}
public void setMean(double mean) {
this.mean = mean;
normal = new NormalDistributionFunction2D(mean,std);
dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal");
repaint();
}
public double getStd() {
return std;
}
public void setStd(double std) {
this.std = std;
}
public JFreeChartPanel(){
JFreeChart chart = ChartFactory.createXYLineChart(
"Normal Distribution",
"X",
"Y",
dataset,
PlotOrientation.VERTICAL,
true,
true,
false
);
final ChartPanel chartPanel = new ChartPanel(chart);
setLayout(new BorderLayout());
add(chartPanel);
}
}
And this is executed everytime I change the value in my JTextField.
public void updateMean()
{
String meanS = mean.getText();
double mean = 0.0;
try{
mean = Double.parseDouble(meanS);
System.out.println("Mean: "+mean);
jFreeChartPanel.setMean(mean);
}catch(Exception e){
System.out.println("Mean: incorrect input");
}
}
Ordinarily, you could simply update the XYDataset used to create the JFreeChart, and the listening chart would update itself in response. As #Hovercraft notes, repaint() alone is not sufficient to tell the chart's plot that you have replaced the dataset. In the example below, I've refactored the dataset's initialization and passed it to setDataset() as a parameter.
public void setMean(double mean) {
this.mean = mean;
plot.setDataset(initDataset());
}
See the relevant source to examine the event wiring. A ChangeListener added to a JSpinner may be easier to operate than a JTextField.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.event.ChangeEvent;
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.data.function.Function2D;
import org.jfree.data.function.NormalDistributionFunction2D;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
/**
* #see https://stackoverflow.com/a/40167139/230513
*/
public class TestDistribution {
private static class JFreeChartPanel extends JPanel {
private XYPlot plot;
private double mean = 0.0, sigma = 1.0;
XYDataset dataset = initDataset();
private XYDataset initDataset() {
Function2D normal = new NormalDistributionFunction2D(mean, sigma);
XYDataset dataset = DatasetUtilities.sampleFunction2D(normal, -5.0, 5.0, 100, "Normal");
return dataset;
}
;
public double getMean() {
return mean;
}
public void setMean(double mean) {
this.mean = mean;
plot.setDataset(initDataset());
}
public double getStd() {
return sigma;
}
public void setStd(double sigma) {
this.sigma = sigma;
}
public JFreeChartPanel() {
JFreeChart chart = ChartFactory.createXYLineChart(
"Normal Distribution", "X", "Y", dataset,
PlotOrientation.VERTICAL, true, true, false
);
plot = chart.getXYPlot();
final ChartPanel chartPanel = new ChartPanel(chart);
add(chartPanel);
}
}
private void display() {
JFrame f = new JFrame("TestDistribution");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFreeChartPanel chartPanel = new JFreeChartPanel();
f.add(chartPanel);
JSpinner spinner = new JSpinner();
spinner.setValue(chartPanel.mean);
spinner.addChangeListener((ChangeEvent e) -> {
JSpinner s = (JSpinner) e.getSource();
Number n = (Number) s.getValue();
chartPanel.setMean(n.doubleValue());
});
f.add(spinner, BorderLayout.PAGE_END);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new TestDistribution()::display);
}
}
Requirement: i need to display toolTip(No data available) and image on time series chart which have null data ie; Image 2 on gray color area.
Problem:I am not able to get it.
Image With some data ie; series1.addOrUpdate(absoluteMSecond, data[i]);
Image with null data ie; series1.addOrUpdate(absoluteMSecond, null);
COde:
import java.util.Calendar;
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.ValueAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.Millisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class TextOnJFreeChart extends ApplicationFrame {
public TextOnJFreeChart(final String title) {
super(title);
final XYDataset data = createDataset();
final JFreeChart chart = createChart(data);
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
}
private JFreeChart createChart(final XYDataset data) {
final JFreeChart chart = ChartFactory.createTimeSeriesChart("Text/ToolTip Trying Demo", "X", "Y", data, true, true, true);
final XYPlot plot = chart.getXYPlot();
plot.getRenderer().setToolTipGenerator(StandardXYToolTipGenerator.getTimeSeriesInstance());
plot.setNoDataMessage("Hai it is ok if i get this message.......");
final DateAxis domainAxis = new DateAxis("Time");
domainAxis.setUpperMargin(0.50);
plot.setDomainAxis(domainAxis);
final ValueAxis rangeAxis = plot.getRangeAxis();
rangeAxis.setUpperMargin(0.30);
rangeAxis.setLowerMargin(0.50);
return chart;
}
private XYDataset createDataset() {
final TimeSeriesCollection result = new TimeSeriesCollection();
result.addSeries(createSupplier1Bids());
return result;
}
private TimeSeries createSupplier1Bids()
{
double[] data = {200.0, 195.0, 190.0, 188.0, 185.0, 180.0};
long timeStamp = System.currentTimeMillis();
Millisecond absoluteMSecond = getTimeInMillisecondFormat(timeStamp, 0L);
final TimeSeries series1 = new TimeSeries("Supplier 1", Millisecond.class);
for(int i = 0; i < data.length; i++)
{
absoluteMSecond = getTimeInMillisecondFormat(timeStamp + i * 1000, 0L);
//series1.addOrUpdate(absoluteMSecond, data[i]);
series1.addOrUpdate(absoluteMSecond, null);
}
return series1;
}
public Millisecond getTimeInMillisecondFormat(long timeStamp, long startTime)
{
try
{
long diff = timeStamp - startTime;
Calendar calender = Calendar.getInstance();
calender.setTimeInMillis(diff);
Millisecond elapsedMSecond = new Millisecond(calender.getTime());
return (elapsedMSecond);
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
public static void main(final String[] args) {
final TextOnJFreeChart demo = new TextOnJFreeChart("Text/ToolTip Trying Demo");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
Thanks in advance
You can specify the desired image to the plot's setBackgroundImage() method, mentioned here and here.
The implementation of getToolTipText() in ChartPanel will return null if the dataset is empty, but you can override the method to return a suitable alternative string.
in order to display the gray level histogram of the pixels of an image
I used an object "XYBARCHART" [JFreeChart] I also used a dataset of category XYSeriesCollection and "XYItemRenderer" renderer.
I change the color with the method: this. renderer1.setSeriesPaint (i2, Color.green)
but the series remains with pink color (default). what I want is when I click the red Boutton I display the histogram with red, blue Boutton blue histogram shows ..
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
public class ImgHst implements ActionListener{
private ParameterBlock imgParamBloc;
private PlanarImage imgHistSrc ;
private Histogram imgHistogram;
private int[] histValeurs;
private int bandesCouleurs; //R;G;B
private int maxHistValeurs;
private ChartPanel myChartcontentPane;
private JButton redBtn,greenBtn,blueBtn;
private XYSeriesCollection ensHistg ;
private JFrame frame;
private JFreeChart myChart ;
private XYSeries s,sred,sgreen,sblue;
private XYPlot plot ;
private XYItemRenderer renderer0,renderer1,renderer2;
ImgHst(PlanarImage img)
{
this.imgHistSrc =img ;
imgHistogram = new Histogram(256, 0, 255, 3);
this.histValeurs =imgHistogram .getBins(bandesCouleurs);
maxHistValeurs= 0;
for(int i=0;i<histValeurs.length;i++) maxHistValeurs = Math.max(maxHistValeurs,histValeurs[i]);
imgParamBloc = new ParameterBlock();
imgParamBloc.addSource(img);
imgParamBloc.add(null);
imgParamBloc.add(1);
imgParamBloc.add(1);
// création de l'histograme et remplissage du tableau des niveaux de gris
RenderedOp operateurHtg = JAI.create("histogram", imgParamBloc, null);
imgHistogram = (Histogram) operateurHtg.getProperty("histogram");
createHstFrame();
}
public void setImgSrc(PlanarImage img)
{
imgHistSrc = img;
}
public Histogram getMyHistogram()
{
return imgHistogram;
}
private XYSeries createSerie(int bande_couleur)
{
XYSeries s = new XYSeries("S");
for(int i=0;i < imgHistogram.getNumBins(bande_couleur);i++)
{
s.add(i, imgHistogram.getBinSize(bande_couleur,i));
}
return s;
}
public void setBandeCouleur(int b)
{
this.bandesCouleurs =b;
}
public void createHstFrame()
{
sred=createSerie(0);
sgreen=createSerie(1);
sblue=createSerie(2);
myChart = ChartFactory.createXYBarChart("Histograme", "Intensité",false, "Nombre des Pixels", ensHistg ,PlotOrientation.VERTICAL ,false,true,true);
myChartcontentPane =new ChartPanel(myChart);
// this.myChartcontentPane.setChart(ChartFactory.createXYBarChart("Histograme", "Intensité",false,"Nombre des Pixels", ensHistg,PlotOrientation.VERTICAL ,false,true,true));
ChartUtilities.applyCurrentTheme(myChart);
frame = new JFrame("");
frame.add(myChartcontentPane);
JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
redBtn = new JButton("Red");
redBtn.addActionListener((ActionListener)this);
panel.add(redBtn);
greenBtn = new JButton("Green");
greenBtn.addActionListener((ActionListener)this);
panel.add(greenBtn);
blueBtn = new JButton("Blue");
blueBtn.addActionListener((ActionListener)this);
panel.add(blueBtn);
frame.add(panel, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// return frame;
}
public void createMyChart(XYSeries ss)
{
ensHistg = new XYSeriesCollection(ss);
myChartcontentPane.setChart(ChartFactory.createXYBarChart("Histograme", "Intensité",false, "Nombre des Pixels", ensHistg,PlotOrientation.VERTICAL ,false,true,true));
ChartUtilities.applyCurrentTheme(myChart);
plot= (XYPlot) myChart.getPlot();
ValueAxis xAxis = plot.getDomainAxis();
// ((ValueAxis) xAxis).setLowerBound(0);
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
yAxis.setLowerBound(0);
switch(this. bandesCouleurs)
{
case 0:
this. renderer0 = plot.getRenderer() ;
this. renderer0 = plot.getRenderer() ;
int i1 = ensHistg.indexOf(ss);
this. renderer0.setSeriesPaint(i1, Color.green ) ;System.out.println(bandesCouleurs);
plot.setRenderer( renderer0);
break;
case 1:
this. renderer1 = plot.getRenderer() ;
this. renderer1 = plot.getRenderer() ;
int i2 = ensHistg.indexOf(ss);
this. renderer1.setSeriesPaint(i2, Color.green ) ;System.out.println(bandesCouleurs);
plot.setRenderer( renderer1);
break;
case 2 :this. renderer2 = plot.getRenderer() ;
this. renderer2 = plot.getRenderer() ;
this. renderer2.setSeriesPaint(0, Color.blue ) ;System.out.println(bandesCouleurs);
plot.setRenderer(renderer2);
break;
}
frame.add(myChartcontentPane);
frame.repaint();
}
public void actionPerformed(ActionEvent cliquebtn) {
if (cliquebtn.getSource().equals(redBtn))
{
setBandeCouleur(0);
createMyChart(sred);
}
if (cliquebtn.getSource().equals(greenBtn))
{
setBandeCouleur(1);
createMyChart(sgreen);
}
if (cliquebtn.getSource().equals(blueBtn))
{ setBandeCouleur(2);
createMyChart(sblue);
}
}
}
Your createMyChart() method has this line which assigns a new chart to the ChartPanel, but it is not the same chart object you are referencing in your myChart field:
myChartcontentPane.setChart(ChartFactory.createXYBarChart("Histograme", "Intensité",false, "Nombre des Pixels", ensHistg,PlotOrientation.VERTICAL ,false,true,true));
effectively
sir, I found what you said.
I fixed my problem in the following way but I am not satisfied on the coding
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.Histogram;
import javax.media.jai.JAI;
import javax.media.jai.PlanarImage;
import javax.media.jai.RenderedOp;
import javax.swing.JButton;
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.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
public class ImgHst implements ActionListener{
private ParameterBlock imgParamBloc;
private Histogram imgHistogram;
private int[] histValeurs;
private int bandesCouleurs; //R;G;B
private int maxHistValeurs;
private JButton redBtn,greenBtn,blueBtn;
private XYSeriesCollection ensHistg ;
private JFrame frame;
private XYPlot plot ;
ImgHst(PlanarImage img)
{
imgHistogram = new Histogram(255, 0, 255, 3);
this.histValeurs =imgHistogram .getBins(bandesCouleurs);
maxHistValeurs= 0;
for(int i=0;i<histValeurs.length;i++) maxHistValeurs = Math.max(maxHistValeurs,histValeurs[i]);
imgParamBloc = new ParameterBlock();
imgParamBloc.addSource(img);
imgParamBloc.add(null);
imgParamBloc.add(1);
imgParamBloc.add(1);
// création de l'histograme et remplissage du tableau des niveaux de gris
RenderedOp operateurHtg = JAI.create("histogram", imgParamBloc, null);
imgHistogram = (Histogram) operateurHtg.getProperty("histogram");
createHstFrame();
}
public void setImgSrc(PlanarImage img)
{
}
public Histogram getMyHistogram()
{
return imgHistogram;
}
private XYSeries createSerie(int bande_couleur)
{
XYSeries s = new XYSeries("S");
for(int i=0;i < imgHistogram.getNumBins(bande_couleur);i++)
{
s.add(i, imgHistogram.getBinSize(bande_couleur,i));
}
return s;
}
public void setBandeCouleur(int b)
{
this.bandesCouleurs =b;
}
public ChartPanel getChartPane(int band)
{
ensHistg = new XYSeriesCollection(createSerie(band));
JFreeChart Chart = ChartFactory.createXYBarChart("Histograme", "Intensité",false, "Nombre des Pixels", ensHistg ,PlotOrientation.VERTICAL ,false,true,true);
ChartPanel cPanel= new ChartPanel(Chart);
plot= (XYPlot) Chart.getPlot();
ValueAxis xAxis = plot.getDomainAxis();
((ValueAxis) xAxis).setLowerBound(0);
NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();
yAxis.setLowerBound(0);
XYBarRenderer barRndr = (XYBarRenderer) plot.getRenderer();
switch(band)
{
case 0: barRndr.setSeriesPaint(0, Color.red ) ;
plot.setRenderer( barRndr);
break;
case 1: barRndr.setSeriesPaint(0, Color.green );
plot.setRenderer( barRndr);
break;
case 2 : barRndr.setSeriesPaint(0, Color.blue );
plot.setRenderer( barRndr);
break;
}
return cPanel;
}
public void createHstFrame()
{
frame = new JFrame("");
frame.add(setBtnPanel(), BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private JPanel setBtnPanel()
{
JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
redBtn = new JButton("Red");
redBtn.addActionListener((ActionListener)this);
panel.add(redBtn);
greenBtn = new JButton("Green");
greenBtn.addActionListener((ActionListener)this);
panel.add(greenBtn);
blueBtn = new JButton("Blue");
blueBtn.addActionListener((ActionListener)this);
panel.add(blueBtn);
return panel;
}
public void actionPerformed(ActionEvent cliquebtn) {
if (cliquebtn.getSource().equals(redBtn))
{
frame.getContentPane().removeAll();
frame.getContentPane().repaint();
frame.add(getChartPane(0));
frame.add(setBtnPanel(), BorderLayout.SOUTH);
frame.pack();
}
if (cliquebtn.getSource().equals(greenBtn))
{
frame.getContentPane().removeAll();
frame.getContentPane().repaint();
frame.add(getChartPane(1));
frame.add(setBtnPanel(), BorderLayout.SOUTH);
frame.pack();
}
if (cliquebtn.getSource().equals(blueBtn))
{
frame.getContentPane().removeAll();
frame.getContentPane().repaint();
frame.add(getChartPane(2));
frame.add(setBtnPanel(), BorderLayout.SOUTH);
frame.pack();
}
}
}
I have developed a timeseries JFreeChart by using code from this thread.
I want to add this to my main panel, which contains four other panels. So I created a method
package com.garnet.panel;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.swing.JPanel;
import javax.swing.Timer;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.RefineryUtilities;
public class PrepareChart {
private static final String TITLE = "Dynamic Series";
private static final int COUNT = 2 * 60;
private Timer timer;
private static float lastValue = 49.62f;
ValueAxis axis;
DateAxis dateAxis;
public JFreeChart chart;
public PrepareChart() {
super();
final DynamicTimeSeriesCollection dataset = new DynamicTimeSeriesCollection(1, COUNT, new Second());
// Get the calender date time which will inserted into time series chart
// Based on time we are getting here we disply the chart
Calendar calendar = new GregorianCalendar();
int date = calendar.get(Calendar.DAY_OF_MONTH);
int month = calendar.get(Calendar.MONTH);
int year = calendar.get(Calendar.YEAR);
int hours = calendar.get(Calendar.HOUR_OF_DAY);
int minutes = calendar.get(Calendar.MINUTE);
int seconds = calendar.get(Calendar.SECOND);
System.out.println("In caht constructor methoed");
dataset.setTimeBase(new Second(seconds, minutes-2, hours, date, month, year));
dataset.addSeries(gaussianData(), 0, "Currency Rate");
chart= createChart(dataset);
timer = new Timer(969, new ActionListener() {
float[] newData = new float[1];
#Override
public void actionPerformed(ActionEvent e) {
newData[0] = randomValue();
System.out.println("In caht timer methoed");
dataset.advanceTime();
dataset.appendData(newData);
}
});
}
private float randomValue() {
double factor = 2 * Math.random();
if (lastValue >51){
lastValue=lastValue-(float)factor;
}else {
lastValue = lastValue + (float) factor;
}
return lastValue;
}
// For getting the a random float value which is supplied to dataset of time series chart
private float[] gaussianData() {
float[] a = new float[COUNT];
for (int i = 0; i < a.length; i++) {
a[i] = randomValue();
}
return a;
}
// This methode will create the chart in the required format
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(TITLE, "hh:mm:ss", "Currency", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
plot.setBackgroundPaint(Color.BLACK);
plot.setDomainGridlinePaint(Color.WHITE);
plot.setRangeGridlinePaint(Color.WHITE);
plot.setAxisOffset(new RectangleInsets(5.0, 5.0, 5.0, 5.0));
plot.setDomainCrosshairVisible(true);
plot.setRangeCrosshairVisible(true);
XYItemRenderer r = plot.getRenderer();
if (r instanceof XYLineAndShapeRenderer) {
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) r;
renderer.setBaseShapesVisible(true);
renderer.setBaseShapesFilled(true);
renderer.setBasePaint(Color.white);
renderer.setSeriesPaint(0,Color.magenta);
}
dateAxis= (DateAxis)plot.getDomainAxis();
DateTickUnit unit = null;
unit = new DateTickUnit(DateTickUnitType.SECOND,30);
DateFormat chartFormatter = new SimpleDateFormat("HH:mm:ss");
dateAxis.setDateFormatOverride(chartFormatter);
dateAxis.setTickUnit(unit);
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setRange(lastValue-4, lastValue+4);
return result;
}
public void start(){
timer.start();
}
public JPanel getChartPanel(){
EventQueue.invokeLater(new Runnable() {
public void run() {
PrepareChart chart = new PrepareChart();
System.out.println("In caht getter methoed");
chart.start();
}
});
return new ChartPanel(chart);
}
}
I am calling this code inside one of my panel constructors like this:
public class ChartPanel extends JPanel{
private Dimension dim;
private PrepareChart chart;
public JPanel jChart;
public ChartPanel(){
dim = super.getToolkit().getScreenSize();
this.setBounds(2,2,dim.width/4,dim.height/4);
chart = new PrepareChart();
jChart =chart.getChartPanel();
this.add(jChart);
}
But when I add this panel to the frame, the graph is not changing dynamically.
OK, I think I have spotted your problem, but I can't be completely sure without seeing how you use all this code.
Your main issue lies here:
public JPanel getChartPanel(){
EventQueue.invokeLater(new Runnable() {
public void run() {
PrepareChart chart = new PrepareChart();
System.out.println("In caht getter methoed");
chart.start();
}
});
return new ChartPanel(chart);
}
In your Runnable, you recreate a new instance of PrepareChart and you start it. This does not make any sense:
Your enclosing PrepareChart instance is never started (hence you don't see it updated dynamically)
The instance you create in your runnable cannot be reached by anyone/anything so that instance if lost forever in the AWT event-queue.
So instead, I would only be using the following:
public JPanel getChartPanel() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
start();
}
});
return new ChartPanel(chart);
}
This is a small main method that I wrote which seemed to do the trick.
public static void main(String[] args) {
PrepareChart prepareChart = new PrepareChart();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(prepareChart.getChartPanel());
frame.pack();
frame.setVisible(true);
}
Consider renaming your class ChartPanel because it is conflicting with the names of JFreeChart which is confusing. Also, I don't see the use of it since you could perform all that directly on the ChartPanel returned by PrepareChart.
Btw, it is quite odd to put the call to start() in a getter-method.
i am currently working on a java-based project using JFreeChart to display boxplots.
My Problem is how to display a chart containing boxplots for a CategoryDataset with about 20 Categories and 5+ Series.
Currently if the preferred size of the ChartPanel is not set, the Legend, Labels and Annotations are readable but the Boxplots are too small. Or the size of the ChartPanel is set so that the Boxplots have an acceptable size but then the legend, labels and annotations are horizontally stretched.
My question is, how to correctly scale the boxplots without scaling the legend, axis Labels and annotations of the Chart? Is it possible to scale the Plot without scaling all the elements of the Chart?
Code Example
import java.awt.Color;
import java.awt.Dimension;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;
public class StretchedBoxAndWhiskerExample{
DefaultBoxAndWhiskerCategoryDataset dataset;
JFreeChart chart;
ChartPanel chartPanel;
JFrame frame;
JScrollPane scrollPane;
public StretchedBoxAndWhiskerExample() {
createCategoryBoxplot();
frame = new JFrame();
scrollPane = new JScrollPane(chartPanel);
scrollPane.setPreferredSize(new Dimension(800,700));
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
frame.add(scrollPane);
frame.pack();
frame.setVisible(true);
}
private void createCategoryBoxplot(){
dataset = createCategoryDataset();
CategoryAxis xAxis = new CategoryAxis("");
NumberAxis yAxis = new NumberAxis("Score");
BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
CategoryPlot plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
createJFreeChart(plot,"Test");
// Design
renderer.setFillBox(false);
renderer.setMeanVisible(false);
chart.setBackgroundPaint(Color.white);
plot.setBackgroundPaint(Color.lightGray);
plot.setDomainGridlinePaint(Color.white);
plot.setDomainGridlinesVisible(true);
plot.setRangeGridlinePaint(Color.white);
plot.getRangeAxis().setRange(-10.5, 10.5);
chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new Dimension(3250,600));
}
private DefaultBoxAndWhiskerCategoryDataset createCategoryDataset() {
dataset = new DefaultBoxAndWhiskerCategoryDataset();
ArrayList<Double> values = createSampleData();
ArrayList<String> categories = createSampleCategories();
for (int i=0;i<=5;i++){
for (String category : categories){
dataset.add(values,i,category);
}
}
return dataset;
}
private ArrayList<String> createSampleCategories() {
ArrayList<String> tmp = new ArrayList<String>();
for (int i=0;i<=20;i++){
tmp.add("Category"+i);
}
return tmp;
}
private ArrayList<Double> createSampleData() {
ArrayList<Double> tmp = new ArrayList<Double>();
for (int i=0;i<10;i++){
tmp.add(5.0);
tmp.add(7.0);
tmp.add(2.0);
tmp.add(4.0);
}
return tmp;
}
private void createJFreeChart(CategoryPlot plot, String title){
chart = new JFreeChart(title, plot);
}
public static void main(String[] args) throws IOException {
StretchedBoxAndWhiskerExample demo = new StretchedBoxAndWhiskerExample();
}
}
Set the preferred size of the containing ChartPanel, not the chart, as shown here and here.
Addendum: I don't think you can usefully add a chart to a scroll pane. Instead, create a class similar to SlidingCategoryDataset that implements BoxAndWhiskerCategoryDataset. Add a scroll bar to the frame that controls the first displayed index.
Addendum: A somewhat less ambitious approach is simply to page a portion of the data set using some suitable control, as shown in the example below.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BoxAndWhiskerRenderer;
import org.jfree.data.statistics.DefaultBoxAndWhiskerCategoryDataset;
/** #see https://stackoverflow.com/questions/6844759 */
public class BoxAndWhiskerDemo {
private static final int COLS = 20;
private static final int VISIBLE = 4;
private static final int ROWS = 5;
private static final int VALUES = 10;
private static final Random rnd = new Random();
private List<String> columns;
private List<List<List<Double>>> data;
private DefaultBoxAndWhiskerCategoryDataset dataset;
private CategoryPlot plot;
private ChartPanel chartPanel;
private JPanel controlPanel;
private int start = 0;
public BoxAndWhiskerDemo() {
createData();
createDataset(start);
createChartPanel();
createControlPanel();
}
private void createData() {
columns = new ArrayList<String>(COLS);
data = new ArrayList<List<List<Double>>>();
for (int i = 0; i < COLS; i++) {
String name = "Category" + String.valueOf(i + 1);
columns.add(name);
List<List<Double>> list = new ArrayList<List<Double>>();
for (int j = 0; j < ROWS; j++) {
list.add(createValues());
}
data.add(list);
}
}
private List<Double> createValues() {
List<Double> list = new ArrayList<Double>();
for (int i = 0; i < VALUES; i++) {
list.add(rnd.nextGaussian());
}
return list;
}
private void createDataset(int start) {
dataset = new DefaultBoxAndWhiskerCategoryDataset();
for (int i = start; i < start + VISIBLE; i++) {
List<List<Double>> list = data.get(i);
int row = 0;
for (List<Double> values : list) {
String category = columns.get(i);
dataset.add(values, "s" + row++, category);
}
}
}
private void createChartPanel() {
CategoryAxis xAxis = new CategoryAxis("Category");
NumberAxis yAxis = new NumberAxis("Value");
BoxAndWhiskerRenderer renderer = new BoxAndWhiskerRenderer();
plot = new CategoryPlot(dataset, xAxis, yAxis, renderer);
JFreeChart chart = new JFreeChart("BoxAndWhiskerDemo", plot);
chartPanel = new ChartPanel(chart);
}
private void createControlPanel() {
controlPanel = new JPanel();
controlPanel.add(new JButton(new AbstractAction("\u22b2Prev") {
#Override
public void actionPerformed(ActionEvent e) {
start -= VISIBLE;
if (start < 0) {
start = 0;
return;
}
createDataset(start);
plot.setDataset(dataset);
}
}));
controlPanel.add(new JButton(new AbstractAction("Next\u22b3") {
#Override
public void actionPerformed(ActionEvent e) {
start += VISIBLE;
if (start > COLS - VISIBLE) {
start = COLS - VISIBLE;
return;
}
createDataset(start);
plot.setDataset(dataset);
}
}));
}
public ChartPanel getChartPanel() {
return chartPanel;
}
public JPanel getControlPanel() {
return controlPanel;
}
public static void main(String[] args) throws IOException {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BoxAndWhiskerDemo demo = new BoxAndWhiskerDemo();
frame.add(demo.getChartPanel(), BorderLayout.CENTER);
frame.add(demo.getControlPanel(), BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}