How to customize a bar chart using Achart in andorid - java

I am drawing a bar chart using the Achart Library. I want to customize the chart as follows:
Give space between first bar from start
Increase the width of each bar
Increase text size of numbers which are at top of the bars
The 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);
}][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);

Related

Is there a way I can get the Bar Width in px/dp's of an MP Android BarChart?

I want to create a "table" (which is build with a recycle view) below my chart. But I want the RecycleView to have the same number of elements of my chart (In this case 7) Is there a way to get the column width of the Bar Chartso I can assign the same width to my Recycle View Cells?
At the end (if it is posible) I want the two scroll to be synced.
The bar width in pixels is the difference between the value bar width x position (wp) and the label starting position (xp):
Transformer transformer = bChart.getTransformer(YAxis.AxisDependency.LEFT);
float bw = (float) transformer.getPixelForValues(bChart.getBarData().getBarWidth(), 0).x;
float xp = (float) transformer.getPixelForValues(0, 0).x;
float barWidthInPixels = bw - xp;

How many JLabels fit in my JPanel

I'm trying to fill a JPanel with a neat grid containing as many JLabels as will fit into the JPanel. The size of the JPanel can vary, and the size of the JLabels depends on the label text, the icon included in the JLabel, and the font being used to render the label text.
GridLayout myLayout = new GridLayout();
JPanel myPanel = new JPanel(myLayout);
List<JLabel> myLabels = ...
int panelWidth = myPanel.getWidth();
int panelHeight = myPanel.getHeight();
if (panelWidth == 0 || panelHeight == 0) return;
int maxLabelWidth = 0, maxLabelHeight = 0;
for (JLabel label : myLabels) {
int labelWidth = ???
int labelHeight = ???
if (labelWidth > maxLabelWidth) maxLabelWidth = labelWidth;
if (labelHeight > maxLabelHeight) maxLabelHeight = labelHeight;
}
// Use panelHeight, panelWidth, maxLabelHeight and maxLabelWidth to compute
// rows and columns available for myLayout
myLayout.setRows(nRows); myLayout.setColumns(nColumns);
for (JLabel label : myLabels) {
myPanel.add(label);
// stop if we reach nRows*nColumns labels
}
I've tried myPanel.getGraphics().getFontMetrics().getHeight() to get the height of text, but when the font is large and myPanel is small, the text is taller than labelHeight, and the bottom and top get cut off.
I've tried label.getIcon().getIconHeight() to get the height of the icon, but using this value always cuts off the top and bottom of the icons.
I've tried label.getSize() to get the height and width of the JLabel, but that usually returns 0 height and 0 width. I've tried label.getPreferredSize() but that generally returns a value that's too small.
I've tried label.getGraphics().getFontMetrics().stringWidth(label.getText()) to get the width of the string, and then added that to label.getIcon().getIconWidth() and label.getIcon().getIconTextGap() but that comes up with a value a little larger or smaller than label.getPreferredSize(), and in any case still too small - sometimes the label text is cut off at the end.
At one point I tried adding a constant to each width and height; that prevented cut-off text and icons, but of course it left too much blank space around the JLabels. Is there a way to get an accurate size for each JLabel for this usage?

androidPlot black border

When i execute the code bellow and add in mySimpleXYPlot.getGraphWidget().getBorderPaint().setColor(Color.WHITE);
the app crashes when i launch it on my device.
what i'm trying to accomplish is getting rid of the black border around the entire graph. it is about 2cm thick on located on the top, left and bottom sides of the chart. Is there any way i can get rid of this black border?
public class MainActivity extends Activity {
private XYPlot mySimpleXYPlot;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create a couple arrays of y-values to plot:
Number[] days = { 1 , 2 , 3 , 4 , 5 , 6 , 7 };
Number[] values = { 380, 1433, 1965, 3200, 3651, 3215, 3217 };
// initialize our XYPlot reference:
mySimpleXYPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
mySimpleXYPlot.getBackgroundPaint().setColor(Color.WHITE);
mySimpleXYPlot.setBorderStyle(XYPlot.BorderStyle.NONE, null, null);
mySimpleXYPlot.getGraphWidget().getBackgroundPaint().setColor(Color.WHITE);
mySimpleXYPlot.getGraphWidget().getGridBackgroundPaint().setColor(Color.WHITE);
// Domain
mySimpleXYPlot.getGraphWidget().setDomainLabelPaint(null);
mySimpleXYPlot.getGraphWidget().setDomainOriginLinePaint(null);
mySimpleXYPlot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, days.length);
mySimpleXYPlot.setDomainValueFormat(new DecimalFormat("0"));
//Range
mySimpleXYPlot.getGraphWidget().setRangeOriginLinePaint(null);
mySimpleXYPlot.setRangeStep(XYStepMode.SUBDIVIDE, values.length);
mySimpleXYPlot.setRangeValueFormat(new DecimalFormat("0"));
//Remove legend
mySimpleXYPlot.getLayoutManager().remove(mySimpleXYPlot.getLegendWidget());
mySimpleXYPlot.getLayoutManager().remove(mySimpleXYPlot.getDomainLabelWidget());
mySimpleXYPlot.getLayoutManager().remove(mySimpleXYPlot.getRangeLabelWidget());
mySimpleXYPlot.getLayoutManager().remove(mySimpleXYPlot.getTitleWidget());
// Turn the above arrays into XYSeries':
XYSeries series1 = new SimpleXYSeries(
Arrays.asList(days),
Arrays.asList(values),
"Series1"); // Set the display title of the series
// Create a formatter to use for drawing a series using LineAndPointRenderer:
LineAndPointFormatter series1Format = new LineAndPointFormatter(
Color.rgb(0, 200, 0), // line color
Color.rgb(0, 100, 0), // point color
Color.CYAN); // fill color
// setup our line fill paint to be a slightly transparent gradient:
Paint lineFill = new Paint();
lineFill.setAlpha(200);
lineFill.setShader(new LinearGradient(0, 0, 0, 250, Color.WHITE, Color.GREEN, Shader.TileMode.MIRROR));
series1Format.setFillPaint(lineFill);
// add a new series' to the xyplot:
mySimpleXYPlot.addSeries(series1, series1Format);
// by default, AndroidPlot displays developer guides to aid in laying out your plot.
// To get rid of them call disableAllMarkup():
mySimpleXYPlot.disableAllMarkup();
}
}
If you want to get rid of all of the color behind your graph, you will need the following three methods. Each of which gets rid of different parts.
//This gets rid of the gray grid
mySimpleXYPlot.getGraphWidget().getGridBackgroundPaint().setColor(Color.TRANSPARENT);
//This gets rid of the black border (up to the graph) there is no black border around the labels
mysimpleXYPlot.getBackgroundPaint().setColor(Color.TRANSPARENT);
//This gets rid of the black behind the graph
mySimpleXYPlot.getGraphWidget().getBackgroundPaint().setColor(Color.TRANSPARENT);
//With a new release of AndroidPlot you have to also set the border paint
plot.getBorderPaint().setColor(Color.TRANSPARENT);
Hope this helps.
Border line can be hidden by this method:
plot.setBorderPaint(null);
plot.setPlotMargins(0, 0, 0, 0);
I was able to figure out how to fix the graph with this information but I had to pull together the information from several of these posts. There appears to be 4 different background areas:
* grid (and axis labels)
* area around the graph
* border around the graph.
* margin around the border
The background color for the grid and range/domain labels are set using
plot.getGraphWidget().getBackgroundPaint().setColor(background_color);
The area round the grid can get set by:
plot.getBackgroundPaint().setColor(background_color);
This still leaves a border that is drawn around the graph. You can either get rid of the border:
plot.setBorderPaint(null);
or set the background color
plot.getBorderPaint().setColor(background_color);
This leaves the margin around the entire plot. This can be removed using
plot.setPlotMargins(0, 0, 0, 0);
There should be a way to change the color for the margin instead of just removing it but didn't bother to figure that out.

Slider always has default width in table

I created a slider inside of a table like shown in the following code example as I know that the minimum width of the background is used for the slider width:
public OptionScreen(MainClass game) {
super(game);
preference = new PreferencesHelper();
font = this.getDefaultFont(25);
this.table = new Table();
if (Config.DEBUG)
this.table.debug();
// add volumenlabel
LabelStyle style = new LabelStyle(font, Color.WHITE);
volumenLabel = new Label(Config.VOLUMEN_LABLE, style);
table.add(volumenLabel).colspan(2);
table.row();
// add slider
Skin skin = new Skin();
skin.add("sliderbackground",
this.game.manager.get("data/sliderbackground.png"));
skin.add("sliderknob", this.game.manager.get("data/sliderknob.png"));
SliderStyle sliderStyle = new SliderStyle();
sliderStyle.background = skin.getDrawable("sliderbackground");
sliderStyle.background.setMinWidth(600f);
sliderStyle.knob = skin.getDrawable("sliderknob");
volumenSlider = new Slider(0f, 1f, 0.1f, false, sliderStyle);
volumenSlider.setValue(preference.getVolumen()); // load current volumen
volumenSlider.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
volumeValue.setText(String.format("%.01f",
volumenSlider.getValue()));
// sett the preference
preference.setVolumen(volumenSlider.getValue());
}
});
// add volslider to stage
table.add(volumenSlider);
volumenLabel.invalidate();
// table
style = new LabelStyle(font, Color.WHITE);
// set current volumen
volumeValue = new Label(
String.format("%.01f", volumenSlider.getValue()), style);
volumenLabel.setAlignment(2);
table.add(volumeValue).width(50f);
table.row();
initBackButton();
// init table
table.setPosition(Config.VIRTUAL_VIEW_WIDTH / 2,
Config.VIRTUAL_VIEW_HEIGHT / 2 - Config.BLOCK_SIZE * 10);
// add a nice fadeIn to the whole table :)
table.setColor(0, 0, 0, 0f);
table.addAction(Actions.fadeIn(2f)); // alpha fade
table.addAction(Actions.moveTo(Config.VIRTUAL_VIEW_WIDTH / 2,
Config.VIRTUAL_VIEW_HEIGHT / 2, 2f)); // move to center of the
// screen
// add to stage
this.stage.addActor(table);
}
The slide is inside a table with no width set. I already took a look if the width is set and if the calculation for the prefWidth of the slider does uses the set 600f.
Math.max(style.knob == null ? 0 : style.knob.getMinWidth(), style.background.getMinWidth())
Is the calculation for the width of the slider inside the Sliderclass. If I calculate that and log it, it loggs the desired 600f.
Everything seems right to me but the slider is rendered way to small for the 600 I set.
The background and knobtextures are 24x24.
So I hope you guys can tell me what I am doing wrong.
The folution is, that it's inside an table so the width is defined by the table width attibut for the spec. col and row.
So the fix is pretty short:
table.add(volumenSlider).width(600).height(60);
And its 600width and 60 height.
The wiki got edited to be more clear about this:
UI widgets do not set their own size and position. Instead, the parent widget sets the size and position of each child. Widgets provide a minimum, preferred, and maximum size that the parent can use as hints. Some parent widgets, such as Table, can be given constraints on how to size and position the children. To give a widget a specific size in a layout, the widget's minimum, preferred, and maximum size are left alone and size constraints are set in the parent.
Layout at Wiki
speedSlider.getStyle().knob.setMinHeight(100)

CrossHair Tracing In JFreeChart

I was able to implement real-time mouse tracing as follow :
The source code is as follow :
http://jstock.cvs.sourceforge.net/viewvc/jstock/jstock/src/org/yccheok/jstock/charting/CrossHairUI.java?revision=1.5&view=markup
http://jstock.cvs.sourceforge.net/viewvc/jstock/jstock/src/org/yccheok/jstock/gui/ChartJDialog.java?revision=1.9&view=markup
However, I unable to obtained the correct y screen coordinate, when an subplot being added.
(broken image)
I suspect I didn't get the correct screen data area.
When there is only one plot in the screen, I get a screen data area with height 300++
When a sub plot added to the bottom, I expect screen data area height will be reduced, due to the height occupied by the newly added subplot.
However, I have no idea how to obtain the correct screen data area for the first plot.
final XYPlot plot = (XYPlot) cplot.getSubplots().get(0);
// Shall I get _plotArea represents screen for getSubplots().get(0)?
// How?
// I try
//
// chartPanel.getScreenDataArea(0, 0);
// chartPanel.getScreenDataArea(0, 1);
// chartPanel.getScreenDataArea(1, 0);
// chartPanel.getScreenDataArea(1, 1);
//
// All returned null
// OK. I suspect this is causing me unable to get the correct screen y coordinate
// I always get the same _plotArea, although a new sub plot had been added.
final Rectangle2D _plotArea = chartPanel.getScreenDataArea();
final RectangleEdge rangeAxisEdge = plot.getRangeAxisEdge();
final double yJava2D = rangeAxis.valueToJava2D(yValue, _plotArea, rangeAxisEdge);
Here is the code snippet to obtained the correct rectangle after dive into JFreeChart source code.
/* Try to get correct main chart area. */
final Rectangle2D _plotArea = chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea();

Categories