Adding DateAxis to gantt Chart Javafx - java

I was able to make a Gantt Chart in JavaFX using this answer- Gantt chart from scratch.
Also i was able to add a DateAxis by using this-http://myjavafx.blogspot.com.by/2013/09/javafx-charts-display-date-values-on.html
But right now it is unusable, because current Gantt chart does not handle "length" as a date. So it draws the beginning of the the chart perfectly accurately, but the end of the chart can be anywhere, and if you resize the window with the chart, the end will be even more random.
I am adding new chart with
.add(new XYChart.Data(job.getTime(), machine, new ExtraData( timeLength, "status-red"))
where "timeLength" i set as number of milliseconds. But basicly that does not work, and it can only receive long.Also i cannot use JfreeChart, because i cannot add it FXML which i use.
So how can i get accurate both beginning and the end of each chart?
Thank you.

Add the following function to DateAxis class to calculate the scale factor from milliseconds to visual units.
/**
* #return The scale factor from milliseconds to visual units
*/
public double getScale(){
final double length = getSide().isHorizontal() ? getWidth() : getHeight();
// Get the difference between the max and min date.
double diff = currentUpperBound.get() - currentLowerBound.get();
// Get the actual range of the visible area.
// The minimal date should start at the zero position, that's why we subtract it.
double range = length - getZeroPosition();
return length/diff;
}
Test results
Date startDate=new Date();
long duration = 1000*60*1;//1 hour in milliseconds
series1.getData().add(new XYChart.Data(startDate, machine, new ExtraData(duration, "status-green")));
startDate = new Date(startDate.getTime()+duration);
duration = 1000*60*1;//2 hours in milliseconds
series1.getData().add(new XYChart.Data(startDate, machine, new ExtraData(duration, "status-red")));
screenshot 1

Related

How to prevent candlesticks from overlapping eachother?

I'm trying to plot the candles without them overlapping eachother like in the added image.
I played around a bit with the domain range but i'm having trouble figuring out how to keep/set a minimum spacing between the candles.
If someone could point me in the right direction it would be greatly appreciated.
private DateAxis getTimeAxis() {
final DateAxis dateAxis = new DateAxis("TIME_AXIS");
dateAxis.setDateFormatOverride(DATE_TIME_FORMAT);
// this limits the visible candles but doesnt really solve the problem
// long start= ohlcs_series.getX(0,200).longValue(); // start from index 200
// long end = ohlcs_series.getX(0,607).longValue(); // last candle
//
// dateAxis.setRange(
// new Date(start),
// new Date(end + calculateEmptySpace())
// );
dateAxis.setLowerMargin(-0.025);
dateAxis.setUpperMargin(0.15);
Font bold = dateAxis.getLabelFont().deriveFont(Font.BOLD);
dateAxis.setLabelFont(bold);
return dateAxis;
}
/**
* Returns the width of 50 candles
* This is used to create some empty space after the last candle
* */
private long calculateEmptySpace(){
int indexOfLast = ohlcs_series.getSeries(0).getItemCount()-1;
long lastCandle = ohlcs_series.getX(0, indexOfLast).longValue();
long candle= ohlcs_series.getX(0,indexOfLast-50).longValue();
return lastCandle-candle;
}

Jfree chart value Axis label is getting cropped

I am plotting the bar and line chart using the jfree chart .
One of the value axis is having the large label which doesn't fit in.
The label is suppose to be Greenhouse gas emissions (Tonnes).
Unable to find a way to control the width of the lable or wrap it.
final JFreeChart chart = ChartFactory.createBarChart(chartDetails.getTitle(),
chartDetails.getCategoryAxisLabel(), chartDetails.getValueAxisLabelLabelOne(),
dataSets.get(0),
PlotOrientation.VERTICAL, false,
true,
false
);
final ValueAxis rangeAxis = new NumberAxis(chartDetails.getValueAxisLabelLabelTwo());
plot.setRangeAxis(1, axis2);
final Font yaxisFont = getFont(yaxisFontAttibutes, xfactor);
rangeAxis.setLabelFont(yaxisFont);
rangeAxis.setLabelPaint(Color.decode(yaxisFontAttibutes.getColor()));
rangeAxis.setTickLabelFont(yaxisFont);
rangeAxis.setTickLabelPaint(Color.decode(yaxisFontAttibutes.getColor()));
rangeAxis.setLabelFont(yaxisFont);
rangeAxis.setAxisLineVisible(false);
rangeAxis.setLabelInsets(new RectangleInsets(2, 2, 2, 2));
return chart.createBufferedImage((int) (chartAttributes.getWidth() * xfactor),
(int) chartAttributes.getHeight() * xfactor);
Tried using LabelInsets but no use.
Note: I dont want to increase the heigth
Any sample code will be of great help.
Thanks
I have set the label at high end and rotated it .
But results are not desirable.
rangeAxis.setLabelLocation(AxisLabelLocation.HIGH_END);
rangeAxis.setLabelAngle(135);

JFreeChart with XYBoxAnnotation Open on One Side

I'm using an XYBoxAnnotation to demarcate a rectangular area on a JFreeChart. I would like one side of the box to be "open", i.e go out to infinity. I tried setting the value to Double.POSITIVE_INFINITY but this did not seem to work. I also tried setting it to Double.MAX_VALUE, with no luck either. In these cases, the annotation doesn't even show up on the plot at all. And there are no exceptions thrown.
Below is a very simple version of my code in which I generate the XYBoxAnnotation and add it to the plot.
XYBoxAnnotation _axisMarker = new XYBoxAnnotation(xLow, yLow, Double.POSITIVE_INFINITY, yHigh, new BasicStroke(0.5F), Color.WHITE, Color.WHITE);
_plot.getRenderer().addAnnotation(_axisMarker, Layer.BACKGROUND);
EDIT:
I figured out that the reason the annotation wasn't showing up was because the x value for the annotation was much much larger than the axis scale. For some reason, this causes the annotation to not be visible until you zoom out enough.
Thanks to #trashgod's answer below, I came up with a solution. His answer didn't quite work for me since my plot allows zooming and you could see the edge of the box when you zoomed out.
First, I added a PlotChangeListener to listen for when the plot is zoomed:
// define PlotChangeListener to update the annotation when the plot is zoomed
private PlotChangeListener _zoomListener = new PlotChangeListener() {
#Override
public void plotChanged(PlotChangeEvent plotChangeEvent) {
if (_basisIsotope != null) {
updateAxisMarkers();
}
}
};
Then I created a function to re-draw the annotation based on the new plot bounds:
// function to re-draw the annotation
private void updateAxisMarkers() {
_plot.removeChangeListener(_zoomListener); // remove to prevent triggering infinite loop
// define xLow, yLow and yHigh...
double xHigh = _plot.getDomainAxis().getUpperBound() * 1.1;
XYBoxAnnotation _axisMarker = new = new XYBoxAnnotation(xLow, yLow, xHigh, yHigh, new BasicStroke(0.5F), Color.WHITE, Color.WHITE);
_plot.getRenderer().addAnnotation(annotation);
_plot.addChangeListener(_zoomListener); // add back
}
Double.MAX_VALUE is too large to scale to the relevant axis, but Double.MAX_VALUE / 2 works as well as any value larger than the upper bound of the axis. A better choice might be a value that exceeds the maximum value of the domain by some margin. The fragment below shades a plot of some Gaussian data with an XYBoxAnnotation that has domain bounds extending from 42 to the maximum domain value + 10%; the range bounds are ±1σ.
XYSeriesCollection dataset = createDataset();
JFreeChart chart = createChart(dataset);
Color color = new Color(0, 0, 255, 63);
double max = dataset.getSeries(0).getMaxX() * 1.1;
XYBoxAnnotation annotation = new XYBoxAnnotation(
42, -1, max, 1, new BasicStroke(1f), color, color);
chart.getXYPlot().getRenderer().addAnnotation(annotation);

Jfreechart: Display weeks on x axis for value of days

I am using JFreeChart to display a value for each day of a month.
Now I want to have my x-axis display the weeks in a month instead of the days.
At the moment the values for my graph are double on the y-axis and int on the x axis.
Timestamp ts = a.getTimestamp();
Double val = a.getVal();
series1.add(ts.getDate(), val);
I am using
plot.getDomainAxis().setRange(0, 31);
to set the range for the days to one month and
xax.setTickUnit(new NumberTickUnit(7));
for the x-axis to display the ticks at the right position. Instead of displaying the days (0, 7, 14, 21, 28) i want them to be weeks (0, 1, 2, 3, 4).
Is that even possible, and how would I be able to do that?
You should use a DateAxis for your time axis, like ChartFactory.createTimeSeriesChart() does. Then you can use setDateFormatOverride(), like they show here, and the SimpleDateFormat for "week in month."
JFreeChart chart = ChartFactory.createTimeSeriesChart(…);
DateAxis axis = (DateAxis) chart.getXYPlot().getDomainAxis();
axis.setDateFormatOverride(new SimpleDateFormat("W"));

JFreeChart Margin

I am using JasperReports to create a line chart for my webapps.
I have successfully passed the dataset to the compiled report (created in iReport) and can see the data correctly.
However, I want to do some customization on the margin.
The value shown on the line chart is trimming for the highest value as there is no margin.
The X-Axis label is coming after few empty space from Y-Axis 0 value. I want to remove that margin and start the X-Axis from very close to the meeting point of X & Y.
Please see the picture:
I am using customized class which is defined in my webspps. I am able to change the font size and rotation of the label but don't know how to adjust margin.
public class LineChartCustomizer implements JRChartCustomizer {
#Override
public void customize(JFreeChart jFreeChart, JRChart jrChart) {
CategoryPlot plot = jFreeChart.getCategoryPlot();
DecimalFormat dfKey = new DecimalFormat("###,###");
StandardCategoryItemLabelGenerator labelGenerator = new StandardCategoryItemLabelGenerator("{2}", dfKey);
LineAndShapeRenderer renderer = new LineAndShapeRenderer();
renderer.setBaseItemLabelsVisible(true);
renderer.setBaseItemLabelGenerator(labelGenerator);
renderer.setBaseItemLabelFont(new java.awt.Font("SansSerif", java.awt.Font.PLAIN, 4));
renderer.setSeriesShape(0, ShapeUtilities.createDiamond(1F));
plot.setRenderer(renderer);
}
}
I think* you're looking for ValueAxis#setUpperMargin(double) and CategoryAxis#setLowerMargin(double). You can get the CategoryAxis and ValueAxis from plot.getDomainAxis() and plot.getRangeAxis(). Note that the margins are a percentage of the axis length and not pixel values.
* I'm not familiar with JasperReports, but it seems a little strange that you have a CategoryPlot in hand as opposed to an XYPlot. I would have expected the chart in your picture to have used an xy time series. I have only ever tested this with an XYPlot, so I'm not entirely sure how it will behave with a CategoryPlot.

Categories

Resources