How to add tooltips in JFreechart - jfreechart

I am doing the following to generate the stackedAreaChart
CategoryItemRenderer renderer = new StackedAreaRenderer();
CategoryPlot plot = new CategoryPlot();
plot.setDataset(dataset);
plot.setRenderer(renderer);
JFreeChart chart = new JFreeChart(plot);
how can I show the toop tips for the chart? Thanks.

Related

Telerik: How to set CartesianGridLineAnnotation Background color

So in my application i have chat and i added CartesianGridLineAnnotation:
RadCartesianChart chart;
CartesianGridLineAnnotation cartesianGridLineAnnotation;
cartesianGridLineAnnotation = new CartesianGridLineAnnotation
{
Foreground = Brushes.White,
Background = Brushes.Green,
Axis = chart.VerticalAxis,
Stroke = Brushes.Red,
StrokeThickness = 1,
};
chart.Annotations.Add(...);
So as you can see i try to set Background color but the problem is that i cannot see any change in my CartesianGridLineAnnotation Label.
Other properties when changed look as expected.
Update
This is how i am populate my label:
cartesianGridLineAnnotation.Label = "bla bla";
As you can see i cannot see the backgroud color.

How to make a custom legend in angular-chart.js Pie Chart

I used angular-chart.js in my website to create a Pie chart, and I would like to customize the legend. By default, the legend shows the color and the label. (As shown in the picture below) I would like to add the value/data of that label, like what it shown in the tooltip of the chart.
This is my HTML code:
<canvas id="pie" class="chart chart-pie"
chart-data="chartData" chart-labels="chartLabels" chart-options="chartOptions">
</canvas>
Based on the angular-chart.js documentation, legend is now a Chart.js option so the chart-legend attribute has been removed.
That is why, in my JS code I've tried to add generateLabels, just in case this is what I need to customize the legend:
$scope.chartOptions = {
legend: {
display: true,
labels: {
generateLabels: function(chart){
console.log(chart.config);
}
}
}
};
But whenever I add this lines, it will not show the chart. I think it is an error or something. And I'm not sure, if generateLabels is the right option that I needed.
Can somebody teach me the right way to customize the legend to achieve what I wanted?
Thanks in advance!
Let me try shedding some light/answering your question:
generateLabels: does make custom labels,and replaces templates from v1 but in order to use it you have to get your chart information and reimplement legend labels adhering to the Legend Item Interface found in the docs and code. Sounds a bit cryptic, but in practice is somehow simple and goes like this:
var theHelp = Chart.helpers;
// You need this for later
// Inside Options:
legend: {
display: true,
// generateLabels changes from chart to chart, check the source,
// this one is from the doughnut :
// https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.doughnut.js#L42
labels: {
generateLabels: function(chart) {
var data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc && arc.custom || {};
var getValueAtIndexOrDefault = theHelp.getValueAtIndexOrDefault;
var arcOpts = chart.options.elements.arc;
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
return {
// And finally :
text: ds.data[i] + "% of the time " + label,
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
index: i
};
});
}
return [];
}
}
}
Result:
Codepen: Chart.js Pie Chart Custom Legend Labels
There are other alternatives, if you notice on the pen/pie, the slices also have data information, that is from a plugin (check the pen)
Still another option, is to render the legend labels off canvas,for instance:
myPieChart.generateLegend();
Which gives you this Html:
"<ul class='0-legend'><li><span style='background-color:black'> </span>she returns it </li><li><span style='background-color:white'></span>she keeps it</li></ul>"
I haven't tried it, but I think you can modify it with the global method for your data Legend on the callback an it will give you a block of Html you can insert off canvas.

OxyPlot legend items managing

is there any way to manage items in legend? I mean e.q. remove some items from legend but not from whole plot? I know that each serie in plot is linked with one item in legend, but i want to break this rule and put to legend only selected series.
Thanks for your request.
If you don't assign a title to the series (LineSeries, etc), it won't be represented on the legend:
var plotModel = new PlotModel();
plotModel.LegendTitle = "Legend";
plotModel.LegendPosition = LegendPosition.RightBottom;
plotModel.Series.Add(new LineSeries
{
ItemsSource = someItemSource,
Color = OxyColors.Red,
//Title = "title" <- Title commented
});
Starting v2.0.1, the legend doesn't automatically appear and all PlotModel.LegendXxx members have been removed. You now have to manually add one legend:
var plotModel = new PlotModel();
plotModel.Legends.Add(new Legend() {
LegendTitle = "Legend",
LegendPosition = LegendPosition.RightBottom,
});
plotModel.Series.Add(new LineSeries
{
ItemsSource = someItemSource,
Color = OxyColors.Red,
//Title = "title" <- Title commented
});

Creating Images in WPF without XAML and dispaying

I am trying to create a WPF Chart in c# code and saving it to file without displaying it on screen. This will be in a WCF Service where data is sent to the service, an image is created and and path to the image is returned.
So far I have got the image to save to file and the data on the X & Y axis is displayed but the columns on the graph are not drawn.
Does anyone know why the columns on the chart are not drawing... here is my code:
public void DoWork()
{
var newThread = new Thread(CreateImage);
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
}
public void CreateImage()
{
var grid = new Grid {Width = 800, Height = 600, Background = new SolidColorBrush(Colors.LightBlue)};
var chart = new Chart();
grid.Children.Add(chart);
var renderTarget = new RenderTargetBitmap((int)grid.Width, (int)grid.Height, 96d, 96d, PixelFormats.Default);
var barSeries = new BarSeries
{
Title = "Fruit in Cupboard",
ItemsSource = new[]
{
new KeyValuePair<string, int>("Oranges", 18),
new KeyValuePair<string, int>("Apples", 15),
new KeyValuePair<string, int>("Melons", 2),
new KeyValuePair<string, int>("Pineapples", 4),
new KeyValuePair<string, int>("Plums", 25)
},
IndependentValueBinding = new Binding("Key"),
DependentValueBinding = new Binding("Value")
};
chart.Series.Add(barSeries);
grid.Measure(new Size(grid.Width, grid.Height));
grid.Arrange(new Rect(new Size(grid.Width, grid.Height)));
grid.UpdateLayout();
renderTarget.Render(grid);
var png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(renderTarget));
using (Stream stm = File.Create(string.Format(#"C:/Images/{0}.png", Guid.NewGuid())))
{
png.Save(stm);
}
}
I had exactly this problem with Telerik's RadChart. The explanation was as you wrote in your comment above - the series was being animated in and the snapshot was being taken before they were visible.
My solution was to set the value of the ChartArea.EnableAnimations property to false before rendering it. I am not familiar with the WPF Toolkit Chart but it is likely that there is a similar setting that you can use to disable the animations.
Note that there is a further, related issue with Telerik's BarSeries - it is necessary to set the opacity of the bars to 1. See the Telerik documentation for details.

Force rendering of a WPF control in memory

I have the following code:
void Test()
{
currentImage.Source = GetBitmap();
RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
rtb.Render(currentImage);
}
This code is supposed to render currentImage, which is an Image control in my xaml to a RenderTargetBitmap.
It doesn't work, rtb returns a blank image, the problem is currentImage didn't render itself yet and so this behavior is expected, I think...
To workaround this problem, I wrote this code:
void Test()
{
currentImage.Source = GetBitmap();
this.Dispatcher.BeginInvoke((Action)delegate()
{
RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96.0, 96.0, PixelFormats.Default);
rtb.Render(currentImage);
}, System.Windows.Threading.DispatcherPriority.Render, null);
}
Basically, I wait for currentImage to be rendered and then I can get it properly rendered to my RenderTargetBitmap.
Is there any way to make it work without using this workaround? Force the Image control to render in memory maybe?
thanks!
use a ViewBox to render in memory
Grid grid = new System.Windows.Controls.Grid() { Background = Brushes.Blue, Width = 200, Height = 200 };
Viewbox viewbox = new Viewbox();
viewbox.Child = grid; //control to render
viewbox.Measure(new System.Windows.Size(200, 200));
viewbox.Arrange(new Rect(0, 0, 200, 200));
viewbox.UpdateLayout();
RenderTargetBitmap render = new RenderTargetBitmap(200, 200, 150, 150, PixelFormats.Pbgra32);
render.Render(viewbox);
I think this is a BETTER answer . The viewbox didn't work completely as expected, and it turned out to be an unnecessary overhead.
Here is a copy of that answer (instead of just link)
You need to force a render of the item, or wait for the item to be rendered. You can then use the ActualHeight and ActualWidth properties.
To force a render:
MenuItem item = new MenuItem();
item.Header = "bling";
item.Icon = someIcon;
//Force render
item.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
item.Arrange(new Rect(item.DesiredSize));
In this example the MenuItem has not been given an explicit height or width. However, forcing the render will render it taking the supplied header text and icon into consideration.

Resources