JFree Chart legend with line break - java

I need to add break line in some legend in JFree Chart.
I have some legends with 316 characters and need to break every 80.
Finally, I'll have 4 lines.
Anyway, I tried with "\n", "\u2424" and "
". It did nothing.
(From http://www.jfree.org/forum/viewtopic.php?f=3&t=10226 & http://www.jfree.org/forum/viewtopic.php?f=3&t=22417)
The only solution I could find (but I wished it could be avoided, since I want it to be dynamically done) is to fix a width for each legend, so it should break as I need to.
Edit : that even didn't work.
I'm using jFree Chart 0.9.20
EDIT
For the moment, with a small legend, that's what I have :
It's fine but when I have my long legends :
For that last picture, I logged my legend and break lines are here, but they don't show up with jFree Chart.

Two alternatives to consider: Given an abbreviated legend display string,
Use setLegendItemToolTipGenerator() to display the full, unbroken string as a tool tip.
renderer.setLegendItemToolTipGenerator(
new StandardXYSeriesLabelGenerator("Legend {0}"));
Use addChartMouseListener(), shown here, and forward mouse moved events over the legend to an adjacent text component.

Alright, I made it work as my client wanted.
First, you need to make a new kind of Legend, for example named MyLegend (but please, don't name it like that in the real world).
That class needs to extend Legend and implement Serializable, the same way StandardLegend does.
To be honest, I even copied/pasted the whole StandardLegend in MyLegend.
Then, you can modify the standard legend to your custom one.
For my needs, I changed :
draw() for the height and width calculation of the whole Legend group
drawSeriesElements() to split the legend's label and draw every lines one under another.
// Multi line management for Legend
String[] multiline = item.getItem().getLabel().split(System.getProperty("line.separator"));
for(int j = 0; j<multiline.length; j++) {
RefineryUtilities.drawAlignedString(multiline[j], g2,
(float) item.getLabelPosition().getX(), (float) item
.getLabelPosition().getY() + g2.getFontMetrics().getHeight()*j, TextAnchor.CENTER_LEFT);
}
createDrawableLegendItem() to calculate each item width and height.
Since, now legends are multiline, each line of one item doesn't have the same width than others. We need to find the longest one to define the item's real width.
Same goes for height. Now it's multiline, so it needs to calculate how many lines it got to know the item's real height.
Optionally, you could change drawLegendTitle() to make it multiline too.
When that class is configured as you want to, you need to apply it on your chart.
So, you do as usual :
JFreeChart chart = new JFreeChart(...);
chart.set ... // apply your series and options
MyLegend legend = new MyLegend();
legend.set... // apply your legend options if applicable
chart.setLegend(legend);
That's it.
Result :

Related

RichTextFX line numbers column extended for entire text area

Could someone tell me how to implement RichTextFX CodeArea with line numbers section extended till the end of the area?
This is how it looks like now:
I don't need line numbers after line 12 but I would like to see this grey bar to fill the entire text area.
Something like here:
P.S. I'm not sure if this is even possible.
I know this is a rather old question, but since I had the same problem, let me share the solution I came up with.
What I did is to smuggle in a rectangle and make sure it is the bottom-most element (i.e. basically part of the background). However, there are a few gotchas when doing this, because the underlying CodeArea is not aware of our new node. If you just insert the rectangle, it might get removed when the CodeArea decides to rebuild the nodes. And getting the right width is a bit tricky because the width of line numbers can basically change at any time and the line-number labels themselves fade in and out of existence whenever you scroll.
So, in order to address these issues, my code sits in the layoutChildren() method and is thus called whenever the nodes in the editor have changed. First we check that the rectangle is actually there as the bottom-most node or insert it if missing. Second, we set the width of the rectangle to the width of the first visible line-number label (which might fail if there are no paragraphs at the moment).
The code itself here is in Scala, but probably easy enough to be quickly adapted to Java.
class MyCodeArea extends CodeArea {
protected val gutterRect = new Rectangle()
gutterRect.heightProperty.bind(this.heightProperty)
gutterRect.getStyleClass.add("lineno")
override protected def layoutChildren(): Unit = {
try {
val children = getChildren
if (!(children.get(0) eq gutterRect))
children.add(0, gutterRect)
val index = visibleParToAllParIndex(0)
val wd = getParagraphGraphic(index).prefWidth(-1)
gutterRect.setWidth(wd)
} catch {
case _: Throwable =>
}
super.layoutChildren()
}
}
Unfortunately, the colour of the rectangle must be assimilated manually. The reason is that the Labels used for line numbers use -fx-background-color, whereas the Rectangle uses -fx-fill. Hence, just setting the same CSS class "lineno" (as I did in my code above) does little to get the colour right. But it allowed me to put both into the same CSS class and therefore have one place where I can change it:
.lineno {
-fx-fill: ivory; // or whatever colour you like
-fx-background-color: -fx-fill;
}

Android donut chart fill with multiple colors based on timestamp

I am looking for a chart which will show one circle around that time like 12:00, 01:00 like. Which fills with some colors based on time of activity.
I found this link Create Doughnut Chart Similar to Google Fit but it isn't fit for my requirements.
Please find image below. This is how I am expecting the chart.
Here these colors represent some activity based on timings. I have a set of data with a timestamp and it's activity type.
Can anyone suggest to me how I can draw this chart? Is there any example for this?
Edit
I found this link http://www.androidtrainee.com/draw-android-clock-pie-chart-with-animation/ to draw clock pie view. But stuck at point to set width and fill color like in above image. Right now it's fill different color based on time in full circle. But how do I set width to this clock to fill color and center part blank to show 08:40?
Since these are very specific requirements, it is likely that you will have to create your own custom view on Android. The SO you linked has a few promising libraries linked including fit-chart. The documentation isn't great, but it seems to support adding chart parts with values in 1% steps.
So you would only need to convert your duration data into percent of the circle by using 60 minutes or 12 hours as 100%.
Here is the relevant usage part of fit-chart:
Collection<FitChartValue> values = new ArrayList<>();
values.add(new FitChartValue(30f, 0x2d4302)); // 30f seems to represent 30%
final FitChart fitChart = (FitChart)findViewById(R.id.fitChart);
fitChart.setValues(values);
Another library that looks promising is MPAndroidChart that supports a detailed Pie Chart.
Regarding taking time into account: There are plenty of tutorials on how to draw an analogue clock that should include calculation on how to position the texts around the circle. Here is one SO creating a CustomClock View with multiple tutorials linked.
Regarding setting up your custom view, this 2d-donut-chart tutorial drawing a chart based on Path.arcTo covers all the needed steps.
If you need further help it would be helpful if you add your data structure and what you already tried. But I hope with these libraries and tutorials you can create your desired view.
Regarding updated question: I would suggest that you create your own custom view. My best suggestion is to continue by comparing the ClockPieView.onDraw with the draw methods of the other libraries I mentioned that do draw a doughnut graph with a hole. Research how text can be rendered as part of the onDraw with your specific positioning.
Heres a list of jQuery extensions to do this:
http://www.jquerybyexample.net/2014/02/jquery-html5-library-circular-piechart-graph.html
You can customize the Pie chart of MPAndroidChart library to create this. Here is a similar one created using it.
Here you will find the documentation of the library and this demo application is also helpful.
Here is a sample code you can try out after adding MPAndroid chart library to your project.
List<PieEntry> entries = new ArrayList<>();
//add data entries, 100 will be considered as a full circle
entries.add(new PieEntry(50, ""));
entries.add(new PieEntry(25, ""));
entries.add(new PieEntry(25, ""));
PieDataSet pieDataSet = new PieDataSet(entries, "");
PieChart pieChart1 = (PieChart)rootView.findViewById(R.id.pie_chart1);
pieChart.setMaxAngle(360);
//You can customize the pie chart in many ways to suit your need
pieChart.setCenterTextRadiusPercent(84);
pieChart.setRotationEnabled(false);
pieChart.setRotationAngle(180);
pieChart.setHoleRadius(60f);
pieChart.setDescription(null);
pieChart.setHoleColor(ContextCompat
.getColor(context,R.color.colorTransparent));
pieChart.setBackgroundColor(ContextCompat.getColor(context,
R.color.colorTransparent));
pieChart.setTouchEnabled(false)
pieChart.setDrawCenterText(true);
pieChart.setCenterTextColor(Color.BLACK);
pieChart.setCenterTextSize(16f);
pieChart.setCenterText(status);
//Add animation (optional)
pieChart.animateY(1500);
pieChart.invalidate();

Programmatically translate chart in MPAndroidChart

I'm trying to implement custom gesture logic for a CombinedChart in MPAndroidChart. Effectively, what I want to accomplish is to have a long press 'enable' highlighting of values but a short press & swipe just control panning / translating the chart (when zoomed). This would allow you to highlight values in a zoomed viewport without translating the chart (by long pressing before scrolling), but would also allow you to translate the chart if you wish by scrolling the view before the long press registers. I have figured out how to do all of the gesture interactions I want however I cannot figure out how to translate the chart.
All I'm really looking for is a API that allows me to translate the chart viewport by (dX, dY) in pixels but I can't seem to find anything. The closest I can find is CombinedChart.centerViewTo(...) but this expects you to center over data point values which if used when translating creates a bit of a staggered translation (as you cannot center over a value in-between two data points.
I can include code if needed, but I figured the code may be overly verbose for a simple API query.
So, I'll delete this when / if a better answer arises, but I found a way that suits my needs (yet may not be 'idiomatic'). What I did was the following:
(Given an offset in pixels of (dX, dY) and a CombinedChart named mChart...)
ViewPortHandler vph = mChart.getViewPortHandler();
Matrix transformation = vph.getMatrixTouch();
transformation.postTranslate(-dX, -dY); // unset the negs to make x / y inverted
vph.refresh(transformation, mChart, true);

Remove an axis from JavaFX Chart

I've created a XYChart with numerical values different (for example temperatue with pressure) so I want to draw my own axeS just beside my chart. To do the following I've to unshow the YAxis, how should I do that ?
By using a trick: The Chart needs the Y Axis to remain in place so it knows where to render your content. You can, however, hide it. Hide the tick labels and set the axis' opacity to 0 using this code:
chart.getYAxis().setTickLabelsVisible(false);
chart.getYAxis().setOpacity(0);
The axis will still be there, but not shown.
I found that if I hid the chart using the following code:
chart.getXAxis().setTickLabelsVisible(false);
chart.getXAxis().setTickMarkVisible(false);
((Path)chart.getXAxis().lookup(".axis-minor-tick-mark")).setVisible(false);
Then I get about ~10 pixels less blank space on the bottom. IF the space was an issue for your application then you could use css offsets to correct it. This solution may have more predictable offsets.
SOLVED: I got this to work for sharing a common x-axis for two charts stacked vertically:
Create two charts, each with their own identical copy of the x-axis object, setting identical upper and lower bounds (optionally by binding).
Then hide the x-axis in the second chart like this:
chart = new LineChart<Number,Number>(xaxis2,yaxis2) {
{// hide xAxis in constructor, since not public
getChartChildren().remove(getXAxis());
// not getPlotChildren()
}
};
You'll want to set the widths of your y-axes to be the identical, e.g.
int w = 60;
yaxis.setMaxWidth(w);
yaxis.setMinWidth(w);
yaxis.setPrefWidth(w);
yaxis2.setMaxWidth(w);
yaxis2.setMinWidth(w);
yaxis2.setPrefWidth(w);

About Y-axis in JFreeChart

The left three lines of data: 0.9,2450,0.4867 in the Y-axis is shown in proportion.
Right three lines (the other two data is too small to show up), how to do the left?
I see several alternatives:
Condition your data to show relative change, as is done in the chart on the left.
Add a second axis to show the larger dynamic range, as is done in DualAxisDemo2.
Enable the zoom feature in ChartPanel, as suggested in this example.

Categories

Resources