Stacked Bar with same item repeating in a line - jfreechart

I have been trying to plot this Stacked Bar Chart in Java using JFreeChart for a wile now.
The problem appears when I try to add the same item "A1" after "A3". Instead of adding another "A1" it replaces the previous "A1",
I have tried to use DefaultMultiValueCategoryDataset but could not manage to make it work.
The code I used is shown below:
DefaultCategoryDataset data = new DefaultCategoryDataset();
data.addValue(2d, "A1", "test");
data.addValue(3d, "A3", "test");
data.addValue(5d, "A2" , "test");
// If I add this it will replace the previous "A1", which is not want I want…
// data.addValue(3d, "A1", "test");
JFreeChart chart = ChartFactory.createStackedBarChart(
null,
"Question Node", // domain axis label
"Forecast Time (months/quarters/years)", // range axis label
data, // data
PlotOrientation.HORIZONTAL, // the plot orientation
true, // include legend
true, // tooltips
false // urls
);

Related

Highcharts conditionally disable marker on hover

New to highcharts - I've got a chart that I have markers disabled on series
plotOptions: {
series: {
marker: {
enabled: false
}
}
},
which is great for the drawing of the lines, but, when I hover over the chart the markers are there. this is good, however, I do not want the marker to be present if the y value on the xAxis is 0 (empty) but I do want them when the y value on the xAxis is greater than one.
I was able to do this before by just setting the y value to null, disabling hover for that series, but the nulls present on this series - drawn as a stacked areaspline graph causes the spline to get drawn improperly (no spline, jagged edges when using the connectNulls: true option in series.
So how do I, and/or can I, conditionally disable a marker on hover based on the y value on an xAxis?
I have been looking at wrapping highcharts prototypes, which I am already doing to control some crosshair behavior drawCrosshair(): https://www.highcharts.com/docs/extending-highcharts/extending-highcharts but I can't seem to find anything that controls the drawing of the markers at that level
A very static approach to this is simply addressing each point with Y-value of 0. Then you could disable the hover-marker for each of these. One such point would look like this (JSFiddle demo):
{
y:0,
marker:{
states:{
hover:{
enabled:false
}
}
}
}
And used in a series:
series: [{
marker: {
enabled: false
},
data: [3, {y:0, marker:{states:{hover:{enabled:false}}}}, 3, 5, 1, 2, 12]
}]
As you can see, it's not pretty, but might help those who need an ad-hoc solution.
A dynamic approach to this is intercepting the setState-function of the Point.
For example, wrapping it and preventing the handling if the y-value is 0:
(function (H) {
H.wrap(H.Point.prototype, 'setState', function (proceed, state, move) {
if(this.y === 0) return;
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
});
}(Highcharts));
See this JSFiddle demonstration of it in action.

chartcheet on libxlsxwriter

I'm trying to use the libxlsxwriter C library but I'm struggling to make chartsheets on a new excel sheet (and not a basic chart on a sheet between formulas).
Any Ideas ? Even on how-to hardcode this ?
Edit
This is what I've done so far :
lxw_worksheet *ChartWorksheet = workbook_add_worksheet(workbook, "TTime");
lxw_chart *chart = workbook_add_chart(workbook, LXW_CHART_SCATTER);
lxw_chart_series *AutoWarmSerie = chart_add_series(chart, "", "");
chart_series_set_name(AutoWarmSerie, "AutoEchauff");
// fill the series
chart_series_set_categories(AutoWarmSerie, DataWorksheet->name, 4, Idx, 4 + m_AutoWarmTime.size(), m_DataColumnIdx); // Time
chart_series_set_values(AutoWarmSerie, DataWorksheet->name, 4, m_DataColumnIdx + 1, 4 + m_AutoWarmTime.size(), m_DataColumnIdx + 1); // Temperature
/* Add a chart title and some axis labels. */
chart_title_set_name(chart, "Results of sample analysis");
chart_axis_set_name(chart->x_axis, "Test number");
chart_axis_set_name(chart->y_axis, "Sample length (mm)");
/* Set an Excel chart style. */
chart_set_style(chart, 11);
/* Insert the chart into the worksheet. */
worksheet_insert_chart(ChartWorksheet, CELL("E2"), chart);
But I only get a single chart box on a sheet, and I dunno how to make the box a whole sheet, so...
Chartsheets aren't currently available in libxlsxwriter but they are a planned feature.
Update: Chartsheet support has been added to libxlsxwriter in version 0.8.0.

How to change tooltip on Angular Chart.js

So, I'm using angular-chart-js plugin on an ionic app (Not sure if that relevant).
With linear chart, by default, when clicking on a dot I get a tooltip as shown:
And I want to change the inside of that tooltip, I couldn't find anything on google.
Any help is appreciated
In the chart options you can specify for a chart, you can create a function to return a template for the tooltip.
$scope.chart_options = {
multiTooltipTemplate: function(label) {
return label.label + ': ' + label.value;
}
}
and in your view:
<canvas id="" class="chart chart-bar" legend="true"
series="bar_series" colours="colors"
data="bar_data" labels="bar_labels"
options="chart_options">
The label object looks like
label = {value: 55, label: "8/18 - 8/24", datasetLabel: "Foo",
strokeColor: "rgba(178,145,47,1)", fillColor: "rgba(178,145,47,0.2)"…}
Edit: The multiTooltipTemplate is used for bar, line, etc, where you have multiple data points for each x axis value. For pie or doughnut, you would just use tooltipTemplate.
I know this is an old question but just for anyone else looking for this - there is a simpler way to customize the tooltips globally.
In your module:
myApp.config(['ChartJsProvider', function (ChartJsProvider) {
ChartJsProvider.setOptions({
tooltipFillColor: '#EEE',
tooltipFontColor: '#000',
tooltipFontSize: 12,
tooltipCornerRadius: 3
});
There are other options to customize the tooltips and almost everything else globally
// Boolean - Whether to animate the chart
animation: true,
// Number - Number of animation steps
animationSteps: 60,
// String - Animation easing effect
animationEasing: "easeOutQuart",
// Boolean - If we should show the scale at all
showScale: true,
// Boolean - If we want to override with a hard coded scale
scaleOverride: false,
// ** Required if scaleOverride is true **
// Number - The number of steps in a hard coded scale
scaleSteps: null,
// Number - The value jump in the hard coded scale
scaleStepWidth: null,
// Number - The scale starting value
scaleStartValue: null,
// String - Colour of the scale line
scaleLineColor: "rgba(0,0,0,.1)",
// Number - Pixel width of the scale line
scaleLineWidth: 1,
// Boolean - Whether to show labels on the scale
scaleShowLabels: true,
// Interpolated JS string - can access value
scaleLabel: "<%=value%>",
// Boolean - Whether the scale should stick to integers, and not show any floats even if drawing space is there
scaleIntegersOnly: true,
// Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
scaleBeginAtZero: false,
// String - Scale label font declaration for the scale label
scaleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Scale label font size in pixels
scaleFontSize: 12,
// String - Scale label font weight style
scaleFontStyle: "normal",
// String - Scale label font colour
scaleFontColor: "#666",
// Boolean - whether or not the chart should be responsive and resize when the browser does.
responsive: false,
// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
maintainAspectRatio: true,
// Boolean - Determines whether to draw tooltips on the canvas or not - attaches events to touchmove & mousemove
showTooltips: true,
// Boolean - Determines whether to draw built-in tooltip or call custom tooltip function
customTooltips: false,
// Array - Array of string names to attach tooltip events
tooltipEvents: ["mousemove", "touchstart", "touchmove", "mouseout"],
// String - Tooltip background colour
tooltipFillColor: "rgba(0,0,0,0.8)",
// String - Tooltip label font declaration for the scale label
tooltipFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip label font size in pixels
tooltipFontSize: 14,
// String - Tooltip font weight style
tooltipFontStyle: "normal",
// String - Tooltip label font colour
tooltipFontColor: "#fff",
// String - Tooltip title font declaration for the scale label
tooltipTitleFontFamily: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
// Number - Tooltip title font size in pixels
tooltipTitleFontSize: 14,
// String - Tooltip title font weight style
tooltipTitleFontStyle: "bold",
// String - Tooltip title font colour
tooltipTitleFontColor: "#fff",
// String - Tooltip title template
tooltipTitleTemplate: "<%= label%>",
// Number - pixel width of padding around tooltip text
tooltipYPadding: 6,
// Number - pixel width of padding around tooltip text
tooltipXPadding: 6,
// Number - Size of the caret on the tooltip
tooltipCaretSize: 8,
// Number - Pixel radius of the tooltip border
tooltipCornerRadius: 6,
// Number - Pixel offset from point x to tooltip edge
tooltipXOffset: 10,
// String - Template string for single tooltips
tooltipTemplate: "<%if (label){%><%=label%>: <%}%><%= value %>",
// String - Template string for single tooltips
multiTooltipTemplate: "<%= datasetLabel %>: <%= value %>",
// String - Colour behind the legend colour block
multiTooltipKeyBackground: '#fff',
// Array - A list of colors to use as the defaults
segmentColorDefault: ["#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", "#FB9A99", "#E31A1C", "#FDBF6F", "#FF7F00", "#CAB2D6", "#6A3D9A", "#B4B482", "#B15928" ],
// Array - A list of highlight colors to use as the defaults
segmentHighlightColorDefaults: [ "#CEF6FF", "#47A0DC", "#DAFFB2", "#5BC854", "#FFC2C1", "#FF4244", "#FFE797", "#FFA728", "#F2DAFE", "#9265C2", "#DCDCAA", "#D98150" ],
// Function - Will fire on animation progression.
onAnimationProgress: function(){},
// Function - Will fire on animation completion.
onAnimationComplete: function(){}
Well, I needed to change my tooltips to make them have the same content of their respective labels, BUT with a detail: make it even if the labels are hidden in the chart. Like this:
This image above shows a chart TIME x VALUE where the interval of time is 20 minutes. That is, I wanted the tooltips to have their respective values of the label (e.g.: on the image, I put the mouse in the value corresponding to the time 18:10, the half of the interval).
All I needed to do was:
1. Create a static array in my class (lazy way to make it more accessible)
public static arrayTooltip = [];
2. Initialized it and filled it in with the proper values of the labels
3. I hid the labels I wanted to hide (no worries... data are safe due to step 2)
And then, in the chart options, I made something like this:
tooltips: {
enabled: true,
displayColors: false,
xPadding: 15,
yPadding: 15,
callbacks: {
title: function(tooltipItem, data) {
return "";
},
label: function(tooltipItem, data) {
return MyClassComponent.arrayTooltip[tooltipItem.index]
}
}
},
In the code above, keep your focus in the callbacks. I didn't want a title, so I made it blank. About the label, I took the index of the current tooltip (the one that is on the aim of the mouse) and used it in the static array. And it is done.
Here is a Plunker. For demo purpose. the message is this is a tooltip
Note: You'll have to create tool tip for complete array object data that is used by the charts to plot.
I hope it solves your issue.

JFreeChart - Datasets versus Series?

I am creating an XYPlot with initially null dataset, and then add multiple (e.g. 2) XYSeriesCollection instances to it. Like
val chart = ChartFactory.createXYLineChart(...)
val plot = chart.getXYPlot
plot.setDataset(0, dataset0)
plot.setDataset(1, dataset1)
Now I want them to have them in different colors and strokes:
import BasicStroke._
val renderer = plot.getRenderer
renderer.setSeriesPaint(0, Color.black)
renderer.setSeriesPaint(1, Color.red)
renderer.setSeriesStroke(0, new BasicStroke(2.0f))
renderer.setSeriesStroke(1,
new BasicStroke(2.0f, CAP_ROUND, JOIN_ROUND, 1.0f, Array(6f, 6f), 0f))
)
But both appear in black and non-dashed. So I must be making a mistake in terms of understanding the correspondence between datasets and series?
I also tried with plot.getRendererForDataset(dataset), but again, both datasets are controlled by the settings for series 0, while the renderer settings for series 1 seem to be irrelevant.
I don't know what the purpose of plot.setDataset(idx, _) is, but the XYSeriesCollection itself needs to have the different series included.
val series: Seq[XYSeries] = ...
val dataset = new XYSeriesCollection
series.foreach(dataset.addSeries _)
val chart = ChartFactory.createXYLineChart("title", "x", "y", dataset,
PlotOrientation.VERTICAL, true, false, false)
val plot = chart.getXYPlot
val renderer = plot.getRenderer
renderer.setSeriesPaint (0, paint0 )
renderer.setSeriesStroke(0, stroke0)
renderer.setSeriesPaint (1, paint1 )
renderer.setSeriesStroke(1, stroke1)
...

ext js 4 column chart bug? series remain visible when I hide them

Feeling I had not enough control over the chart if I had used a grouped column chart, I made my own version by just adding different series to the chart. After all the store, the number of series, their colors and such all need to be set dynamically and not hard coded. So basically this is what I have:
chart = Ext.create("Ext.chart.Chart", {
store: dataStore,
axes: dynamicAxes,
series: series
});
I leave out the not interesting stuff such as width, height of the chart etc.
now I have a method whichs returns a series object. This is added to the series array mentioned in the code above. The function has a "item" object parameter and also an idx param which is the index of the item object from the array it comes from, and a max param which is the size of the item array
the function returns something like this:
var w = (typeof (max) !== "undefined" && max !== null) ? this._getWidthByMax(max) : 30;
return {
type: "column",
axis = "left",
xField = "timestamp",
yField = item.id, // store field name equals the id of the item object
style = { stroke: colorCode, "stroke-width": (item.isDefault) ? 2 : 1, fill: colorCode },
width = w,
renderer = function (sprite, rec, attr, bix) {
var nx = idx * w;
return Ext.apply(attr, { translation: { x: nx} });
}
}
now this works fine for the number of columns I want to have. That can be one, two, three... up to seven currently.
However, if I want to hide a series, the following call doesn't work:
chart.series.getAt(idx).hideAll();
while it does work if I render my chart as a line chart.
is this a bug in Ext-js 4 or is it because of how I rendered the series for my column chart?
since nobody has replied to my question and I have found a solution in the meantime, I might as well answer my own question...
the problem occurred in Ext Js 4.0.7.
With version 4.1 RC 2 the hideAll behaved correctly.
So the solution, for anyone who would have the same problem, is to upgrade to 4.1 RC 2 or newer.

Resources