I have a realtime time series chart where I add vertical value markers when certain events occur. I want to also label those markers with XYTextAnnotation (also vertically). I tried to locate the label along the right side and top of the marker. However, the Y axis of chart uses AutoRange but the annotation is in an absolute X,Y location. The result is that it moves off the chart in the Y axis and disappears as the range increases. How can I add the label so it stays on the chart relative to the changing range? TIA.
Here is my current code:
public void addMarker(String id_,String name_) {
Functions.logger("Adding open door marker for "+id_+" "+name_,false);
Long tod=new Date().getTime();
ValueMarker marker=new ValueMarker(tod);
XYTextAnnotation label=new XYTextAnnotation("Door Open: "+name_,tod-1,360);
label.setRotationAnchor(TextAnchor.BASELINE_CENTER);
label.setTextAnchor(TextAnchor.BASELINE_CENTER);
label.setRotationAngle(-Math.PI/2);
label.setPaint(Color.BLACK);
marker.setStroke(new BasicStroke(2));
marker.setPaint(Color.BLACK);
chart.addDomainMarker(marker);
chart.addAnnotation(label);
}
Related
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);
I am using androidplot with PanZoom attached:
PanZoom.attach(plot);
Therefore I can zoom in and out as it should.
What I want next is to draw a circle at a given point.
Right now I use the strokewidth to set the dimension of the circle.
But when I zoom in and out, the circle size remains the same, although it should scale according to the zoom level. So imagine I zoom in infinitely, the circle should at a certain amount of zoom level cover the whole screen.
But it does not.
How can I achieve this?
I was thinking aboud increasing the strokewidth of the circle according to the zoomlevel but I was neither able to get the zoomlevel nor to get the domain levels on the left and right side of the plot.
EDIT:
In xml folder I create a file e.g. circle.xml:
<?xml version="1.0" encoding="utf-8"?>
<config
fillPaint.color="#00000000"
linePaint.color="#00000000"
linePaint.strokeWidth="0dp"
pointLabelFormatter.textPaint.color="#FFFFFF"
vertexPaint.color="#371cd1d4"
vertexPaint.strokeWidth="20dp"/>
and in java
sigmaLabelFormatter = new LineAndPointFormatter();
sigmaLabelFormatter.setPointLabelFormatter(new PointLabelFormatter());
sigmaLabelFormatter.configure(activity.getApplicationContext(), R.xml.circle);
sigmaLabelFormatter.setPointLabelFormatter(null);
Zoom only affects the drawing of XYSeries data; if you draw directly on the canvas, it will be drawn exactly where you specify on the canvas regardless of pan/zoom.
One thing you can do though is to make series to represent your circle and draw the circle there. This will make the circle respond to both pan and zoom actions. The tricky part will be picking enough points to ensure that the circle appears smooth at your highest supported zoom level.
I found a solution to my problem, since I finally managed:
to get the domain levels on the left and right side of the plot.
or to be more precise to get the width of the plot.
Since the dimensions of the plot is in meters, I do the calculation as follows:
private float calculateDP(float px){
return px / (densityDpi / densityDefault);
}
private float pixelsPerMeter(float value){
float w = plot.getGraph().getWidgetDimensions().canvasRect.width();
float w2 = plot.getBounds().getWidth().floatValue();
return value * (w / w2);
}
private void init(Activity activity){
densityDpi = activity.getResources().getDisplayMetrics().densityDpi;
densityDefault = android.util.DisplayMetrics.DENSITY_DEFAULT;
}
private void onCreate(){
// ... lots of stuff
labelFormatter.getVertexPaint().setStrokeWidth(calculateDP(pixelsPerMeter(2)));
}
Might it help somebody out there...
I am drawing a bar chart using a chart i want to customize the chart.
give spave between first bar from start
Increase the width of each bar
incerese text size of numbers which are at top of the bars
Following is the code for my bar chart
private void openChart()
{
int[] x = { 0,1,2,3,4,5,6};
// Creating an XYSeries for Income
XYSeries wSeries = new XYSeries("Workout");
// Creating an XYSeries for Expense
for(int i=0;i<x.length;i++){
wSeries.add(i,workout[i]);
}
// Creating a dataset to hold each series
XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
// Adding Income Series to the dataset
dataset.addSeries(wSeries);
// Adding Expense Series to dataset
// Creating XYSeriesRenderer to customize incomeSeries
XYSeriesRenderer wRenderer = new XYSeriesRenderer();
wRenderer.setColor(getResources().getColor(R.color.header_blue)); //color of the graph set to cyan
wRenderer.setFillPoints(true);
wRenderer.setLineWidth(5);
wRenderer.setDisplayChartValues(true);
wRenderer.setDisplayChartValuesDistance(20); //setting chart value distance
// Creating a XYMultipleSeriesRenderer to customize the whole chart
XYMultipleSeriesRenderer multiRenderer = new XYMultipleSeriesRenderer();
multiRenderer.setOrientation(XYMultipleSeriesRenderer.Orientation.HORIZONTAL);
multiRenderer.setXLabels(0);
/***
* Customizing graphs
*/
//setting text size of the title
multiRenderer.setChartTitleTextSize(30);
//setting text size of the axis title
multiRenderer.setAxisTitleTextSize(30);
//setting text size of the graph lable
multiRenderer.setLabelsTextSize(30);
//setting zoom buttons visiblity
multiRenderer.setZoomButtonsVisible(false);
//setting pan enablity which uses graph to move on both axis
multiRenderer.setPanEnabled(false, false);
//setting click false on graph
multiRenderer.setClickEnabled(false);
//setting zoom to false on both axis
multiRenderer.setZoomEnabled(false, false);
//setting lines to display on y axis
multiRenderer.setShowGridY(false);
//setting lines to display on x axis
multiRenderer.setShowGridX(false);
//setting legend to fit the screen size
multiRenderer.setFitLegend(true);
//setting displaying line on grid
multiRenderer.setShowGrid(false);
//setting zoom to false
multiRenderer.setZoomEnabled(false);
//setting external zoom functions to false
multiRenderer.setExternalZoomEnabled(false);
//setting displaying lines on graph to be formatted(like using graphics)
multiRenderer.setAntialiasing(true);
//setting to in scroll to false
multiRenderer.setInScroll(false);
//setting to set legend height of the graph
multiRenderer.setLegendHeight(30);
//setting x axis label align
multiRenderer.setXLabelsAlign(Align.CENTER);
//setting y axis label to align
multiRenderer.setYLabelsAlign(Align.RIGHT);
//setting text style
multiRenderer.setTextTypeface("sans_serif", Typeface.BOLD);
//change y axis label color
multiRenderer.setYLabelsColor(0,Color.BLACK);
//change x axis label color
multiRenderer.setXLabelsColor(Color.BLACK);
//setting no of values to display in y axis
multiRenderer.setYLabels(7);
// setting y axis max value, Since i'm using static values inside the graph so i'm setting y max value to 4000.
// if you use dynamic values then get the max y value and set here
multiRenderer.setYAxisMin(0);
multiRenderer.setYAxisMax(49);
//setting used to move the graph on xaxiz to .5 to the right
multiRenderer.setXAxisMin(0);
//setting max values to be display in x axis
multiRenderer.setXAxisMax(7);
//setting bar size or space between two bars
multiRenderer.setBarSpacing(3);
//Setting background color of the graph to transparent
multiRenderer.setBackgroundColor(Color.TRANSPARENT);
//Setting margin color of the graph to transparent
multiRenderer.setMarginsColor(getResources().getColor(R.color.light_red));
multiRenderer.setApplyBackgroundColor(true);
//setting the margin size for the graph in the order top, left, bottom, right
multiRenderer.setMargins(new int[]{20, 40, 20, 20});
for(int i=0; i< x.length;i++){
multiRenderer.addXTextLabel(i, week[i]);
}
// Adding incomeRenderer and expenseRenderer to multipleRenderer
// Note: The order of adding dataseries to dataset and renderers to multipleRenderer
// should be same
multiRenderer.addSeriesRenderer(wRenderer);
//this part is used to display graph on the xml
LinearLayout chartContainer = (LinearLayout) findViewById(R.id.nut_sum_graphLayout);
//remove any views before u paint the chart
chartContainer.removeAllViews();
//drawing bar chart
mChart = ChartFactory.getBarChartView(HealthNutritionSummary.this, dataset, multiRenderer,Type.DEFAULT);
//adding the view to the linearlayout
chartContainer.addView(mChart);
}![enter image description here][2]
to give space on the left side a chart, I set X axis min to smaller size. For example, this should do the trick in your case.
multiRenderer.setXAxisMin(-0.5);
To increase width, you have two options.You can set bar spacing or bar width.
multiRenderer.setBarSpacing(0.5);
or
multiRenderer.setBarWidth(20); // I think this is in pixels
And finally, for text size there is option for XYSeriesRenderer, in your case:
wRenderer.setChartValuesTextSize(20);
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.
I'm drawing within a servlet a ScatterPlot and serve it to the browser.
The user can now click somewhere on the plot and I want to determine what
datapoint of the scatter plot the user has pointed. From the mouse click of the
user I can determine on which pixel of the image he has clicked, but how can
I get from this info to the coordinates on the domain and range axis?
I found tipps how to do it, which uses the ChartPanel. But for serving it directly
to the browser I only use an instance of a JFreeChar object.
Anybody has a clue or an example how to do it?
Thanks,
Dieter
I think I have found a solution. For the solution I need to get my chart again,
so I either have to create it a new or to save it somehow. But when I have a reference
to that chart the solution is as following:
JFreeChart chart = functionWhichRetrievesTheChart();
ChartRenderingInfo info = new ChartRenderingInfo();
// PLOT_SIZE is the size if the graph and has to be the same size as the original drawn chart.createBufferedImage(PLOT_SIZE, PLOT_SIZE, info);
graph, otherwise the pixel position points to somewhere else
PlotRenderingInfo plotInfo = info.getPlotInfo();
XYPlot plot = (XYPlot)chart.getPlot();
Point p = new Point(x,y); // x and y are the pixel positions
// this is the domain value which belongs to the pixel position x
double domain = plot.getDomainAxis().java2DToValue(p.getX(), plotInfo.getDataArea(), plot.getDomainAxisEdge());
// this is the range value which belongs to the pixel position y
double range = plot.getRangeAxis().java2DToValue(p.getY(), plotInfo.getDataArea(), plot.getRangeAxisEdge());