Changing the colors of Gantt renderer - java

I want to change the colors of the renderers in my chart. I'm using JFreeChart
in the same line. I want to have different collors according to the task description.
The problem is I keep having the same color in a line.
package testJFreeChart;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.geom.Rectangle2D;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.CategoryItemEntity;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.labels.IntervalCategoryItemLabelGenerator;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.CategoryItemRendererState;
import org.jfree.chart.renderer.category.GanttRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.GanttCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RectangleEdge;
import org.jfree.ui.RefineryUtilities;
import org.jfree.ui.TextAnchor;
public class GanttDemo2 extends ApplicationFrame {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final TaskSeriesCollection model = new TaskSeriesCollection();
public GanttDemo2(final String title) {
super(title);
final IntervalCategoryDataset dataset = createSampleDataset();
// create the chart...
final JFreeChart chart = ChartFactory.createGanttChart(
"Diagramme de Gantt", // chart title
"Processus", // domain axis label
"temps(ms)", // range axis label
dataset, // data
true, // include legend
true, // tooltips
false // urls
);
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
DateAxis range = (DateAxis) plot.getRangeAxis();
range.setDateFormatOverride(new SimpleDateFormat("SSS"));
range.setMaximumDate(new Date(300));
// add the chart to a panel...
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
//GanttRenderer personnalisé..
MyRenderer renderer = new MyRenderer(model);
renderer.setBaseItemLabelGenerator(new CategoryItemLabelGenerator() {
public String generateLabel(CategoryDataset dataSet, int series, int categories) {
String label = "task";
return label;
}
public String generateColumnLabel(CategoryDataset dataset, int categories) {
//System.out.println(dataset.getColumnKey(categories).toString());
return dataset.getColumnKey(categories).toString();
}
public String generateRowLabel(CategoryDataset dataset, int series) {
return dataset.getRowKey(series).toString();
}
});
renderer.setBaseItemLabelsVisible(true);
renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(ItemLabelAnchor.OUTSIDE9, TextAnchor.CENTER_LEFT));
plot.setRenderer(renderer);
plot.setBackgroundPaint(Color.WHITE);
}
/** #see http://stackoverflow.com/questions/8938690 */
private static class MyRenderer extends GanttRenderer {
private static final int PASS = 2; // assumes two passes
private final List<Color> clut = new ArrayList<Color>();
private final TaskSeriesCollection model;
private int row;
private int col;
private int index;
public MyRenderer(TaskSeriesCollection model) {
this.model = model;
}
#Override
public Paint getItemPaint(int row, int col) {
if (clut.isEmpty() || this.row != row || this.col != col) {
initClut(row, col);
this.row = row;
this.col = col;
index = 0;
}
int clutIndex = index++ / PASS;
return clut.get(clutIndex);
}
private void initClut(int row, int col) {
clut.clear();
Color result = Color.cyan;
TaskSeries series = (TaskSeries) model.getRowKeys().get(row);
List<Task> tasks = series.getTasks(); // unchecked
int taskCount = tasks.get(col).getSubtaskCount();
taskCount = Math.max(1, taskCount);
System.out.println("---->" + taskCount);
String description;
for (int i = 0; i < taskCount; i++) {
// if(taskCount!=1){
//clut.remove(result);
description = tasks.get(col).getSubtask(i).getDescription();
System.out.println(description + " " + i);
if (description.equals("bloque")) {
result = Color.green;
clut.add(result);
System.out.println("yessssss");
}
if (description.equals("ES")) {
result = Color.yellow;
clut.add(result);
}
if (description.equals("Exec")) {
result = Color.blue;
clut.add(result);
System.out.println("NOOOOO");
}
// }
clut.add(result);
}
}
}
private IntervalCategoryDataset createSampleDataset() {
final TaskSeries s1 = new TaskSeries("");
final Task t = new Task("P0", new SimpleTimePeriod(30, 50));
final Task st0 = new Task("Exec", new SimpleTimePeriod(10, 20));
// Task st01 = new Task( "ES",new SimpleTimePeriod(30,60));
t.addSubtask(st0);
// t.addSubtask(st01);
s1.add(t);
final Task t1 = new Task("P1", new SimpleTimePeriod(5, 10));
final Task st11 = new Task("ES", new SimpleTimePeriod(10, 20));
Task st12 = new Task("Exec", new SimpleTimePeriod(30, 60));
t1.addSubtask(st11);
t1.addSubtask(st12);
s1.add(t1);
final Task t3 = new Task("P2", new SimpleTimePeriod(0, 40));
final Task st31 = new Task("bloque", new SimpleTimePeriod(5, 30));
final Task st32 = new Task("Exec", new SimpleTimePeriod(50, 60));
t3.addSubtask(st31);
t3.addSubtask(st32);
s1.add(t3);
model.add(s1);
return model;
}
public static void main(final String[] args) {
final GanttDemo2 demo = new GanttDemo2("Gantt Chart Demo 2");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}

It should be row 1 color blue; row 2 color yellow then blue; row 3 color green then blue.
The variation below seems to produce the desired result. Note that legend will not use the new colors unless you use the approach suggested here.
Console:
----> 1
exec: 0
blue
----> 2
ES: 0
yellow
exec: 1
blue
----> 2
bloque: 0
green
exec: 1
blue
Code:
package chart;
import java.awt.Color;
import java.awt.Paint;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
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.plot.CategoryPlot;
import org.jfree.chart.renderer.category.GanttRenderer;
import org.jfree.data.category.IntervalCategoryDataset;
import org.jfree.data.gantt.Task;
import org.jfree.data.gantt.TaskSeries;
import org.jfree.data.gantt.TaskSeriesCollection;
import org.jfree.data.time.SimpleTimePeriod;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;
public class GanttDemo2 extends ApplicationFrame {
private static final long serialVersionUID = 1L;
public static final TaskSeriesCollection model = new TaskSeriesCollection();
public GanttDemo2(final String title) {
super(title);
final IntervalCategoryDataset dataset = createSampleDataset();
// create the chart...
final JFreeChart chart = ChartFactory.createGanttChart(
"Diagramme de Gantt", // chart title
"Processus", // domain axis label
"temps(ms)", // range axis label
dataset, // data
false, // include legend
true, // tooltips
false // urls
);
final CategoryPlot plot = (CategoryPlot) chart.getPlot();
DateAxis range = (DateAxis) plot.getRangeAxis();
range.setDateFormatOverride(new SimpleDateFormat("SSS"));
range.setMaximumDate(new Date(100));
// add the chart to a panel...
final ChartPanel chartPanel = new ChartPanel(chart);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(chartPanel);
//GanttRenderer personnalisé..
MyRenderer renderer = new MyRenderer(model);
plot.setRenderer(renderer);
plot.setBackgroundPaint(Color.WHITE);
}
/**
* #see https://stackoverflow.com/questions/8938690
*/
private static class MyRenderer extends GanttRenderer {
private static final int PASS = 2; // assumes two passes
private final List<Color> clut = new ArrayList<>();
private final TaskSeriesCollection model;
private int row;
private int col;
private int index;
public MyRenderer(TaskSeriesCollection model) {
this.model = model;
}
#Override
public Paint getItemPaint(int row, int col) {
if (clut.isEmpty() || this.row != row || this.col != col) {
initClut(row, col);
this.row = row;
this.col = col;
index = 0;
}
int clutIndex = index++ / PASS;
return clut.get(clutIndex);
}
private void initClut(int row, int col) {
clut.clear();
TaskSeries series = (TaskSeries) model.getRowKeys().get(row);
List<Task> tasks = series.getTasks(); // unchecked
int taskCount = tasks.get(col).getSubtaskCount();
taskCount = Math.max(1, taskCount);
System.out.println("----> " + taskCount);
String description;
for (int i = 0; i < taskCount; i++) {
description = tasks.get(col).getSubtask(i).getDescription();
System.out.println(description + ": " + i);
if (description.equals("bloque")) {
clut.add(Color.green);
System.out.println("green");
}
if (description.equals("ES")) {
clut.add(Color.yellow);
System.out.println("yellow");
}
if (description.equals("exec")) {
clut.add(Color.blue);
System.out.println("blue");
}
}
}
}
private IntervalCategoryDataset createSampleDataset() {
final TaskSeries s1 = new TaskSeries("");
final Task t0 = new Task("P0", new SimpleTimePeriod(30, 50));
final Task st0 = new Task("exec", new SimpleTimePeriod(10, 20));
// Task st01 = new Task( "ES",new SimpleTimePeriod(30,60));
t0.addSubtask(st0);
// t.addSubtask(st01);
s1.add(t0);
final Task t1 = new Task("P1", new SimpleTimePeriod(5, 10));
final Task st11 = new Task("ES", new SimpleTimePeriod(10, 20));
Task st12 = new Task("exec", new SimpleTimePeriod(30, 60));
t1.addSubtask(st11);
t1.addSubtask(st12);
s1.add(t1);
final Task t2 = new Task("P2", new SimpleTimePeriod(0, 40));
final Task st31 = new Task("bloque", new SimpleTimePeriod(5, 30));
final Task st32 = new Task("exec", new SimpleTimePeriod(50, 60));
t2.addSubtask(st31);
t2.addSubtask(st32);
s1.add(t2);
model.add(s1);
return model;
}
public static void main(final String[] args) {
final GanttDemo2 demo = new GanttDemo2("Gantt Chart Demo 2");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}

Related

Jfreechart make a dynamic scrollable chart [duplicate]

How can I use JFreeChart to display just the most recent data in a continually updated time series?
Addenda: A complete, working example that incorporates the accepted answer is shown here. See also this variation having two series. See also this Q&A regarding setTimeBase().
The JFreeChart class DynamicTimeSeriesCollection is a good choice.
Addendum: As noted by #Bahadır, the last point of the series was persistently zero. #Don helpfully suggests advancing the time and then appending the data.
dataset.advanceTime();
dataset.appendData(newData);
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JComboBox;
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.ValueAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.time.DynamicTimeSeriesCollection;
import org.jfree.data.time.Second;
import org.jfree.data.xy.XYDataset;
import org.jfree.chart.ui.ApplicationFrame;
import org.jfree.chart.ui.UIUtils;
/**
* #see http://stackoverflow.com/a/15521956/230513
* #see http://stackoverflow.com/questions/5048852
*/
public class DTSCTest extends ApplicationFrame {
private static final String TITLE = "Dynamic Series";
private static final String START = "Start";
private static final String STOP = "Stop";
private static final float MINMAX = 100;
private static final int COUNT = 2 * 60;
private static final int FAST = 100;
private static final int SLOW = FAST * 5;
private static final Random random = new Random();
private Timer timer;
public DTSCTest(final String title) {
super(title);
final DynamicTimeSeriesCollection dataset =
new DynamicTimeSeriesCollection(1, COUNT, new Second());
dataset.setTimeBase(new Second(0, 0, 0, 1, 1, 2011));
dataset.addSeries(gaussianData(), 0, "Gaussian data");
JFreeChart chart = createChart(dataset);
final JButton run = new JButton(STOP);
run.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (STOP.equals(cmd)) {
timer.stop();
run.setText(START);
} else {
timer.start();
run.setText(STOP);
}
}
});
final JComboBox combo = new JComboBox();
combo.addItem("Fast");
combo.addItem("Slow");
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if ("Fast".equals(combo.getSelectedItem())) {
timer.setDelay(FAST);
} else {
timer.setDelay(SLOW);
}
}
});
this.add(new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(640, 480);
}
}, BorderLayout.CENTER);
JPanel btnPanel = new JPanel(new FlowLayout());
btnPanel.add(run);
btnPanel.add(combo);
this.add(btnPanel, BorderLayout.SOUTH);
timer = new Timer(FAST, new ActionListener() {
float[] newData = new float[1];
#Override
public void actionPerformed(ActionEvent e) {
newData[0] = randomValue();
dataset.advanceTime();
dataset.appendData(newData);
}
});
}
private float randomValue() {
return (float) (random.nextGaussian() * MINMAX / 3);
}
private float[] gaussianData() {
float[] a = new float[COUNT];
for (int i = 0; i < a.length; i++) {
a[i] = randomValue();
}
return a;
}
private JFreeChart createChart(final XYDataset dataset) {
final JFreeChart result = ChartFactory.createTimeSeriesChart(
TITLE, "hh:mm:ss", "milliVolts", dataset, true, true, false);
final XYPlot plot = result.getXYPlot();
ValueAxis domain = plot.getDomainAxis();
domain.setAutoRange(true);
ValueAxis range = plot.getRangeAxis();
range.setRange(-MINMAX, MINMAX);
return result;
}
public void start() {
timer.start();
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
DTSCTest demo = new DTSCTest(TITLE);
demo.pack();
UIUtils.centerFrameOnScreen(demo);
demo.setVisible(true);
demo.start();
}
});
}
}
You can also eliminate the zero by first advanceTime(), then appendData. (swap the way they are doing it in the example).
One alternative approach to #thrashgod's answer would be to use TimeSeriesCollection and setting item age on the TimeSeries. Below code can setup a graph to show last 1 hour of data with 1 minute intervals.
private TimeSeriesCollection dataset;
private TimeSeries sensorSeries;
sensorSeries = new TimeSeries("name", Minute.class);
sensorSeries.setMaximumItemAge(60);
dataset = new TimeSeriesCollection();
dataset.addSeries(sensorSeries);
..and you will add the data as it comes with:
sensorSeries.add(new Minute(new Date()), newData);

How to draw moving and Running sine wave chart using JFree chart in java?

I m using JFreeChart to draw Running or Moving Sine Wave in java with netbeans. I write code for it , but it does not like moving or running sine wave graph. So if you have any idea regarding that then suggest me.
My code is below
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
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.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
public class DrawChart extends ApplicationFrame implements ActionListener {
public XYSeries series;
public DrawChart(final String title) {
super(title);
series = new XYSeries("Sine", true, true);
XYSeriesCollection dataset = new XYSeriesCollection(series);
final JFreeChart chart = createChart(dataset);
final ChartPanel chartPanel = new ChartPanel(chart);
final JButton button = new JButton("Add New Data Item");
button.setActionCommand("ADD_DATA");
button.addActionListener(this);
final JPanel content = new JPanel(new BorderLayout());
content.add(chartPanel);
content.add(button, BorderLayout.SOUTH);
chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
setContentPane(content);
}
private JFreeChart createChart(final XYDataset dataset) {
JFreeChart jfreechart = ChartFactory.createXYLineChart("Sin Curve", "Angle (Deg)", "Value", dataset, PlotOrientation.VERTICAL, true, true, true);
jfreechart.setBackgroundPaint(Color.white);
XYPlot xyplot = (XYPlot) jfreechart.getPlot();
xyplot.setBackgroundPaint(Color.lightGray);
xyplot.setDomainGridlinePaint(Color.white);
xyplot.setRangeGridlinePaint(Color.white);
return jfreechart;
}
public void actionPerformed(final ActionEvent e) {
if (e.getActionCommand().equals("ADD_DATA")) {
for (int i = 0; i < 100; i++) {
final double x = (i)/10.0 ;
final double y = Math.sin(x);
this.series.addOrUpdate(x, y);
}
}
}
public static void main(final String[] args) {
final DrawChart demo = new DrawChart("Dynamic Data view");
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
}
}
Starting from this example, substituting Math.sin() for nextGaussian() produced the illustration below. A javax.swing.Timer paces the animation at 1 Hz.
private ChartPanel createPane() {
final XYSeries series = new XYSeries("Data");
for (int i = 0; i < random.nextInt(N) + N / 2; i++) {
series.add(i, Math.sin(i));
}
XYSeriesCollection dataset = new XYSeriesCollection(series);
new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
series.add(series.getItemCount(), Math.sin(series.getItemCount()));
}
}).start();
…
}
Try this JavaFX. It's more flexible.
This is what I gathered and came up with using JavaFX
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javafx.animation.AnimationTimer;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;
public class ACS extends Application
{
private static final int MAX_DATA_POINTS = 200;
private Series series;
private float xSeriesData = 0;
private final ConcurrentLinkedQueue<Number> dataQ = new ConcurrentLinkedQueue<Number>();
private ExecutorService executor;
private AddToQueue addToQueue;
private Timeline timeline2;
private NumberAxis xAxis;
private void init(final Stage primaryStage)
{
xAxis = new NumberAxis(0, MAX_DATA_POINTS, 1);
xAxis.setForceZeroInRange(false);
xAxis.setAutoRanging(false);
final NumberAxis yAxis = new NumberAxis(0, 200, 1);
yAxis.setAutoRanging(false);
// -- Chart
final LineChart<Number, Number> sc = new LineChart<Number, Number>(xAxis, yAxis) {
// Override to remove symbols on each data point
#Override
protected void dataItemAdded(final Series<Number, Number> series, final int itemIndex, final Data<Number, Number> item)
{}
};
sc.setAnimated(false);
sc.setId("liveAreaChart");
sc.setTitle("Animated Area Chart");
// -- Chart Series
series = new LineChart.Series<Number, Number>();
series.setName("Area Chart Series");
sc.getData().add(series);
final Scene scene = new Scene(sc, 800, 800);
scene.getStylesheets().add("site.css");
sc.getStyleClass().add("thick-chart");
primaryStage.setScene(scene);
}
#Override
public void start(final Stage primaryStage) throws Exception
{
init(primaryStage);
primaryStage.show();
// -- Prepare Executor Services
executor = Executors.newCachedThreadPool();
addToQueue = new AddToQueue();
executor.execute(addToQueue);
// -- Prepare Timeline
prepareTimeline();
}
public static void main(final String[] args)
{
launch(args);
}
private class AddToQueue implements Runnable
{
double PERIOD = 20;
double SCALE = 20;
int pos = 0;
#Override
public void run()
{
try {
final double Min = 20;
final double Max = 55;
// add a item of random data to queue
//uncomment the line below to generate a normal graph
// dataQ.add(Min + (Math.random() * ((Max - Min))));
dataQ.add(((Math.sin((++pos * 2 * Math.PI) / PERIOD) * (SCALE / 2)) + (SCALE / 2)));
Thread.sleep(1000);
executor.execute(this);
}
catch (final InterruptedException ex) {
// Logger.getLogger(ACS.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
// -- Timeline gets called in the JavaFX Main thread
private void prepareTimeline()
{
// Every frame to take any data from queue and add to chart
new AnimationTimer() {
#Override
public void handle(final long now)
{
addDataToSeries();
}
}.start();
}
private void addDataToSeries()
{
for (int i = 0; i < 20; i++) { // -- add 20 numbers to the plot+
if (dataQ.isEmpty()) {
break;
}
// series.getData().add(new LineChart.Data(xSeriesData++, dataQ.remove()));
final Number datapoint = dataQ.remove();
xSeriesData = xSeriesData + 1;
System.out.println(xSeriesData + " " + datapoint);
series.getData().add(new LineChart.Data(xSeriesData, datapoint));
}
// remove points to keep us at no more than MAX_DATA_POINTS
if (series.getData().size() > (MAX_DATA_POINTS * 10)) {
series.getData().remove(0, series.getData().size() - (MAX_DATA_POINTS * 10));
}
// update
xAxis.setLowerBound(xSeriesData - (MAX_DATA_POINTS));
xAxis.setUpperBound(xSeriesData - 1);
}
}

Changing shape of single point in JFreeChart XYPLot

I am using JFreeChart XYPLot for plotting a XYData set with different labels . I have created different XYSeries objects for different labels so that I can have different colors for different labels . Now I need to require the change the shapes of specific points(test data) in each XYDataSeries as below .
In the above plotting , there are two different XYSeries with blue and red color . Out of these two I need to change the shapes of some points(test data) to X instead of circle . Is it possible in JFreeChart. This post explained on how to do it for whole data set , but I want to change only specific points
Below is the code I have written so far
public static Map<String, XYSeries> createXYSeries(Data[] dataSet){
Map<String,XYSeries> xySeries = new HashMap<String, XYSeries>();
for(Data data : dataSet){
if(xySeries.get(data.actualLabel) == null){
xySeries.put(data.actualLabel, new XYSeries(data.actualLabel));
}
xySeries.get(data.actualLabel).add(data.dimensionValues[0],data.dimensionValues[1]);
}
return xySeries;
}
public XYDataset createXYSeriesCollection(Map<String, XYSeries> plottingDataSet) {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
for (String key : plottingDataSet.keySet()) {
xySeriesCollection.addSeries(plottingDataSet.get(key));
}
return xySeriesCollection;
}
private ChartPanel createPlottingPanel(String title,
Map<String, XYSeries> plottingDataSet) {
JFreeChart jfreechart = ChartFactory.createScatterPlot(title, "X", "Y",
createSampleData(plottingDataSet), PlotOrientation.VERTICAL,
true, true, false);
XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
xyPlot.setBackgroundPaint(Color.white);
return new ChartPanel(jfreechart);
}
Note : I am trying to plot the KNearestNeighbors results .(Circles for train data and X for test data)
ChartFactory.createScatterPlot() instantiates an XYLineAndShapeRenderer. You can replace the renderer with one that lets you selectively replace the Shape returned by getItemShape(), as shown below.
xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {
#Override
public Shape getItemShape(int row, int col) {
if (row == 0 & col == N) {
return ShapeUtilities.createDiagonalCross(5, 2);
} else {
return super.getItemShape(row, col);
}
}
});
Complete example, as run:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Shape;
import java.util.*;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
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;
import org.jfree.util.ShapeUtilities;
/**
* #see http://stackoverflow.com/a/20359200/230513
* #see http://stackoverflow.com/a/6669529/230513
*/
public class ScatterShape extends JFrame {
private static final int N = 8;
private static final int SIZE = 345;
private static final String title = "Scatter Shape Demo";
private static final Random rand = new Random();
private final XYSeries series = new XYSeries("Data");
public ScatterShape(String s) {
super(s);
final ChartPanel chartPanel = createDemoPanel();
this.add(chartPanel, BorderLayout.CENTER);
}
private ChartPanel createDemoPanel() {
JFreeChart chart = ChartFactory.createScatterPlot(
title, "X", "Y", createSampleData(),
PlotOrientation.VERTICAL, true, true, false);
XYPlot xyPlot = (XYPlot) chart.getPlot();
xyPlot.setDomainCrosshairVisible(true);
xyPlot.setRangeCrosshairVisible(true);
xyPlot.setRenderer(new XYLineAndShapeRenderer(false, true) {
#Override
public Shape getItemShape(int row, int col) {
if (row == 0 & col == N) {
return ShapeUtilities.createDiagonalCross(5, 2);
} else {
return super.getItemShape(row, col);
}
}
});
adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
xyPlot.setBackgroundPaint(Color.white);
return new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(SIZE, SIZE);
}
};
}
private void adjustAxis(NumberAxis axis, boolean vertical) {
axis.setRange(-3.0, 3.0);
axis.setTickUnit(new NumberTickUnit(0.5));
axis.setVerticalTickLabels(vertical);
}
private XYDataset createSampleData() {
XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
for (int i = 0; i < N * N; i++) {
series.add(rand.nextGaussian(), rand.nextGaussian());
}
xySeriesCollection.addSeries(series);
return xySeriesCollection;
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ScatterShape demo = new ScatterShape(title);
demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
demo.pack();
demo.setLocationRelativeTo(null);
demo.setVisible(true);
}
});
}
}

Update graph with JFreeChart and slider

I have a time history for arrays describing the pressure along a pipe. So I have an array of pressure values along the length of the pipe for each delta t. I want to plot the pressures along the length of the pipe with JFreeChart and chose which delta t to plot with a slider, so that whenever the user moves the slider the graphic is updates with values from a different delta t. I'm also resetting the tile to be the pressure at the last portion of the pipe. What happens is that the title is updates, meaning the data is being properly updates, but the curve remains the same. I have read every possible topic on forums and tried everything I could think of but it's not working! Here's the code of my class that extends JPanel, in which the method jSlider1StateChanged hears the change in the slider position, createChart creaters a new chart when the program is started, and dataSetGen(int ndt) generates the graph's new dataset based on the slider position:
public class MyMainPanel extends JPanel {
private JFreeChart jc;
private OutputPipe op;
private DefaultXYDataset ds;
private javax.swing.JFrame jFrame1;
private javax.swing.JSlider jSlider1;
private pipevisualizer.MyChartPanel pnlChartPanel;
private void jSlider1StateChanged(javax.swing.event.ChangeEvent evt) {
int ndt = ((JSlider) evt.
getSource()).
getValue();
System.out.println("Slider1: " + ((JSlider) evt.
getSource()).
getValue());
dataSetGen(ndt);
int a = 0;
jc.fireChartChanged();
}
private void dataSetGen(int ndt) {
ArrayList<OutputPipeDt> opDtArray = op.getOpLit();
OutputPipeDt opDt = opDtArray.get(ndt);
double[] H = opDt.getH();
double[] l = new double[H.length];
double[] p = new double[H.length];
double dX = op.getPipeLength() / H.length;
double slope = op.getPipeSlope();
double el = op.getPipeUSElev();
for (int i = 0; i < H.length; i++) {
l[i] = dX * i;
p[i] = el - dX * slope * i;
}
double[][] dataH = new double[2][H.length];
dataH[0] = l;
dataH[1] = H;
double[][] dataP = new double[2][H.length];
dataP[0] = l;
dataP[1] = p;
ds = new DefaultXYDataset();
ds.addSeries("pipe head", dataH);
ds.addSeries("pipe profile", dataP);
jc.setTitle("H[end] = " + Double.toString(dataH[1][l.length - 1]));
jc.fireChartChanged();
}
private JFreeChart createChart(OutputPipe op, int ndt) {
ArrayList<OutputPipeDt> opDtArray = op.getOpLit();
OutputPipeDt opDt = opDtArray.get(ndt);
double[] H = opDt.getH();
double[] l = new double[H.length];
double[] p = new double[H.length];
double dX = op.getPipeLength() / H.length;
double slope = op.getPipeSlope();
double el = op.getPipeUSElev();
for (int i = 0; i < H.length; i++) {
l[i] = dX * i;
p[i] = el - dX * slope * i;
}
double[][] dataH = new double[2][H.length];
dataH[0] = l;
dataH[1] = H;
double[][] dataP = new double[2][H.length];
dataP[0] = l;
dataP[1] = p;
DefaultXYDataset ds = new DefaultXYDataset();
ds.addSeries("pipe head", dataH);
ds.addSeries("pipe profile", dataP);
JFreeChart chart = ChartFactory.createXYLineChart(
"t = " + Double.toString(op.getOpLit().get(ndt).getT()),
// chart title
"X",
// x axis label
"Y",
// y axis label
ds,
// data
PlotOrientation.VERTICAL,
true,
// include legend
true,
// tooltips
false // urls
);
return chart;
}
}
I thought that any changes to the datasets would make the graph redraw itself.
Sorry if the code might be to big to be on the post, but I don't know exactly which parts should I paste to be more or less clear.
Absent a complete example, you may be able to use the approach shown here; it uses plot.setDataset() to replace the dataset on receiving each event.
Addendum: This example that shows temperature versus length over time may get you started.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
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.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
/**
* #see https://stackoverflow.com/a/15207445/230513
*/
public class ChartSliderTest {
private static final int N = 25;
private static final double K = 273.15;
private static final Random random = new Random();
private static XYDataset getDataset(int n) {
final XYSeries series = new XYSeries("Temp (K°)");
double temperature;
for (int length = 0; length < N; length++) {
temperature = K + n * random.nextGaussian();
series.add(length + 1, temperature);
}
return new XYSeriesCollection(series);
}
private static JFreeChart createChart(final XYDataset dataset) {
JFreeChart chart = ChartFactory.createXYLineChart(
"ChartSliderTest", "Length (m)", "Temp (K°)", dataset,
PlotOrientation.VERTICAL, false, false, false);
return chart;
}
private static void display() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final List<XYDataset> list = new ArrayList<XYDataset>();
for (int i = 0; i <= 10; i++) {
list.add(getDataset(i));
}
JFreeChart chart = createChart(list.get(5));
final XYPlot plot = (XYPlot) chart.getPlot();
plot.getRangeAxis().setRangeAboutValue(K, K / 5);
ChartPanel chartPanel = new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(800, 400);
}
};
f.add(chartPanel);
final JSlider slider = new JSlider(0, 10);
slider.addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
plot.setDataset(list.get(slider.getValue()));
}
});
Box p = new Box(BoxLayout.X_AXIS);
p.add(new JLabel("Time:"));
p.add(slider);
f.add(p, BorderLayout.SOUTH);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
display();
}
});
}
}

JFreeChart line chart with text at each point

I would like put text over each point I plotted in a line chart.
This is what I can do:
And this is what I need (names of point are in green):
The StandardXYItemLabelGenerator should work; there's an example here.
Addendum: The labels you can see in the picture are in a separate string array.
Such labels may be incorporated in the XYDataset, as shown in LabeledXYDataset below. Because none of the features of StandardXYItemLabelGenerator are used, a custom implementation of XYItemLabelGenerator is sufficient. The XYItemRenderer controls the color, size and relative position of the labels.
Addendum: How can I add tooltips?
Guided by ChartFactory.createXYLineChart(), simply specify a XYToolTipGenerator to the renderer. The default format, seen here, is Series: (x, y).
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
import java.awt.Color;
import java.awt.Dimension;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.AbstractXYDataset;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.TextAnchor;
/** #see https://stackoverflow.com/a/14459322/230513 */
public class UnitPrice {
private static XYDataset createDataset() {
LabeledXYDataset ds = new LabeledXYDataset();
ds.add(11, 0, "");
ds.add(12, 68, "A");
ds.add(13, 65, "B");
ds.add(14, 67, "C");
ds.add(15, 69, "D");
ds.add(16, 60, "F");
ds.add(17, 83, "G");
ds.add(18, 86, "H");
ds.add(19, 70, "I");
ds.add(20, 60, "J");
ds.add(21, 55, "K");
ds.add(22, 54, "L");
ds.add(23, 50, "M");
return ds;
}
private static class LabeledXYDataset extends AbstractXYDataset {
private static final int N = 26;
private List<Number> x = new ArrayList<Number>(N);
private List<Number> y = new ArrayList<Number>(N);
private List<String> label = new ArrayList<String>(N);
public void add(double x, double y, String label){
this.x.add(x);
this.y.add(y);
this.label.add(label);
}
public String getLabel(int series, int item) {
return label.get(item);
}
#Override
public int getSeriesCount() {
return 1;
}
#Override
public Comparable getSeriesKey(int series) {
return "Unit";
}
#Override
public int getItemCount(int series) {
return label.size();
}
#Override
public Number getX(int series, int item) {
return x.get(item);
}
#Override
public Number getY(int series, int item) {
return y.get(item);
}
}
private static class LabelGenerator implements XYItemLabelGenerator {
#Override
public String generateLabel(XYDataset dataset, int series, int item) {
LabeledXYDataset labelSource = (LabeledXYDataset) dataset;
return labelSource.getLabel(series, item);
}
}
private static JFreeChart createChart(final XYDataset dataset) {
NumberAxis domain = new NumberAxis("Unit");
NumberAxis range = new NumberAxis("Price");
domain.setAutoRangeIncludesZero(false);
XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false);
renderer.setBaseItemLabelGenerator(new LabelGenerator());
renderer.setBaseItemLabelPaint(Color.green.darker());
renderer.setBasePositiveItemLabelPosition(
new ItemLabelPosition(ItemLabelAnchor.CENTER, TextAnchor.CENTER));
renderer.setBaseItemLabelFont(
renderer.getBaseItemLabelFont().deriveFont(14f));
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
XYPlot plot = new XYPlot(dataset, domain, range, renderer);
JFreeChart chart = new JFreeChart(
"Unit Price", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
return chart;
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
XYDataset dataset = createDataset();
JFreeChart chart = createChart(dataset);
ChartPanel chartPanel = new ChartPanel(chart) {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 320);
}
};
f.add(chartPanel);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Use XYTextAnnotation:
for(int i = 0; i < data.length; i++){
XYTextAnnotation textAnnotaion = new XYTextAnnotation(
"" + data[i][anotation], data[i][X], data[i][Y]);
plot.addAnnotation(textAnnotaion);
}

Categories

Resources