achartengine toScreenPoint(double) always returns

2020-02-14 04:51发布

Every time I call this method it return nullpointerexception:

java.lang.NullPointerException at org.achartengine.chart.XYChart.toScreenPoint(XYChart.java:867)

I see mScreenR of chart is null

Without using this method toScreenPoint(double) the charts works well this is the code:

    package com.insights.insights.gui;

import java.util.ArrayList;

import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
import android.widget.LinearLayout;
import android.widget.Toast;

public class ChartFragment extends Fragment {

    private XYMultipleSeriesRenderer renderer;
    private XYMultipleSeriesDataset dataset;
    private GraphicalView graphicalView;
    private XYSeries firstSeries;
    private XYChart chart=null;

    private String apiKey;
    private ArrayList<Day> days;

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.chart_fragment, container, false);

        v.findViewById(R.idChartFragment.container).requestFocus();

        this.view = v;

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        //      Obtaining data to plot
        Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
        ArrayList<Application> applicationArray = applications.getApplication();

        if (applicationArray != null && !applicationArray.isEmpty()) {
            for (int i = 0; i < applicationArray.size(); i++) {
                if (applicationArray.get(i).getApiKey().equals(apiKey)) {
                    ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
                    for (int j = 0; j < appMetrics.size(); j++) {
                        if (appMetrics.get(j).getMetric().equals("Sessions")) {
                            days = appMetrics.get(j).getDay();
                            break;
                        }
                    }
                }
            }
        }

        // If there isn't any item to plot and show a toast
        if (days == null) {
            Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
            toast.show();
            return;
        }

        // Ploting the items
        dataset = getDataset(days);
        renderer = getRenderer();
        setRendererStyling(renderer);

        // add plot to the layout
        if (graphicalView == null) {
            LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
            chart= new LineChart(dataset, renderer);
            graphicalView = new GraphicalView(getActivity(), chart);
            renderer.setSelectableBuffer(11);

            layout.addView(graphicalView);
        } else{
            graphicalView.repaint();
        }


        if(chart!=null&&firstSeries!=null){
            for(int i=0;i<firstSeries.getItemCount();i++){
                double x = firstSeries.getX(i);
                double y = firstSeries.getY(i);

                double[] screenPoint = chart.toScreenPoint(new double[] { x, y },0);

                Log.i("puntos", x + "," + y + " = "+" ("+screenPoint[0]+", "+screenPoint[1]+")");
            }
        }
    }

    /**
     * Method for set the style of the plotter window and the string at the x
     * axis
     * 
     * @param mRenderer
     *            render to put style in
     * 
     * @param dataSetX
     *            string to set at x axis
     */
    private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
        mRenderer.setApplyBackgroundColor(false);
        mRenderer.setMarginsColor(R.drawable.transperent_color);
        mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
        mRenderer.setShowAxes(false);
        mRenderer.setZoomButtonsVisible(false);
        mRenderer.setExternalZoomEnabled(false);
        mRenderer.setPointSize(20);
        mRenderer.setClickEnabled(false);
        mRenderer.setDisplayValues(false);
        mRenderer.setXLabels(0);
        mRenderer.setYLabels(0);
        mRenderer.setPanEnabled(false);
        mRenderer.setZoomEnabled(false);
        mRenderer.setShowLegend(false);

    }

    /**
     * Method to introduce the values of the y axis
     * 
     * @param dataSetY
     *            data to set at axis y
     * @return the data to set
     */
    private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {

        XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
        firstSeries = new XYSeries("");

        for (int i = 0; i < 12; i++) {

            int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
            firstSeries.add(i, value);

        }
        dataset.addSeries(firstSeries);
        return dataset;
    }

    /**
     * Method for set the style of the line you want to plot and create a new
     * renderer
     * 
     * @return the renderer
     */
    private XYMultipleSeriesRenderer getRenderer() {
        XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();
        XYSeriesRenderer r = new XYSeriesRenderer();
        r.setColor(getResources().getColor(R.color.grey_number_label_background));
        r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
        // r.setDisplayChartValues(true);
        r.setPointStyle(PointStyle.POINT);
        r.setFillPoints(true);
        renderer.addSeriesRenderer(r);
        return renderer;
    }
}

And this is the layout file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+idChartFragment/container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal">

    <LinearLayout
        android:id="@+idChartFragment/Chart"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:orientation="horizontal"/>


    <AbsoluteLayout 
        android:id="@+idChartFragment/absolute"
        android:layout_width="300dp"
        android:layout_height="300dp"/>

</RelativeLayout>

Second Edit:

I want to do something like this:

enter image description here

With my code I do this:

enter image description here

This is my code:

 package com.insights.insights.gui;

import java.util.ArrayList;
import java.util.List;

import org.achartengine.GraphicalView;
import org.achartengine.chart.ClickableArea;
import org.achartengine.chart.LineChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.chart.XYChart;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Layout;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.AbsoluteLayout;
import android.widget.AbsoluteLayout.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.ItemizedOverlay.OnFocusChangeListener;
import com.insights.insights.R;
import com.insights.insights.local.ApplicationsController;
import com.insights.insights.model.AppMetrics;
import com.insights.insights.model.Application;
import com.insights.insights.model.Applications;
import com.insights.insights.model.Day;

/**
 * 
 * @author Manuel Plazas Palacio
 * 
 */
public class ChartFragment extends Fragment {

    private XYMultipleSeriesRenderer renderer;
    private XYMultipleSeriesDataset dataset;
    private GraphicalView graphicalView;
    private XYSeries firstSeries;
    private XYChart chart = null;

    private AbsoluteLayout absoluteLayout;
    private ImageView point;
    private LinearLayout pointInfoConatiner;
    private TextView pointNumberText;
    private TextView pointNameText;
    private TextView pointDateText;

    private Typeface avenirHeavy;
    private Typeface avenirLight;

    private String apiKey;
    private String metricName;
    private ArrayList<Day> days;

    //  The max and the min values displayed
    private double max = 0;
    private double min = 0;

    private View view;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        apiKey = getArguments().getString(getString(R.string.tabs_activity_api_key));
        metricName = "Sessions";
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.chart_fragment, container, false);

        v.findViewById(R.idChartFragment.container).requestFocus();

        this.view = v;

        absoluteLayout = (AbsoluteLayout) v.findViewById(R.idChartFragment.absolute);
        //      pointInfoConatiner = (LinearLayout) v.findViewById(R.idChartFragment.pointInfoContainer);
        //      pointNumberText = (TextView) v.findViewById(R.idChartFragment.pointNumberText);
        //      pointNameText = (TextView) v.findViewById(R.idChartFragment.pointNameText);
        //      pointDateText =  (TextView) v.findViewById(R.idChartFragment.pointDateText);
        //
        //      pointNameText.setText(metricName);

        //      Obtaining data to plot
        Applications applications = ApplicationsController.getInstance(getActivity()).getApplications();
        ArrayList<Application> applicationArray = applications.getApplication();

        if (applicationArray != null && !applicationArray.isEmpty()) {
            for (int i = 0; i < applicationArray.size(); i++) {
                if (applicationArray.get(i).getApiKey().equals(apiKey)) {
                    ArrayList<AppMetrics> appMetrics = applicationArray.get(i).getAppMetrics();
                    for (int j = 0; j < appMetrics.size(); j++) {
                        if (appMetrics.get(j).getMetric().equals(metricName)) {
                            days = appMetrics.get(j).getDay();
                            break;
                        }
                    }
                }
            }
        }

        // If there isn't any item to plot and show a toast
        if (days == null) {
            Toast toast = Toast.makeText(getActivity(), R.string.chart_fragment_no_items, Toast.LENGTH_LONG);
            toast.show();
        }

        // Ploting the items
        dataset = getDataset(days);
        renderer = getRenderer();
        setRendererStyling(renderer);

        // add plot to the layout
        if (graphicalView == null) {
            LinearLayout layout = (LinearLayout) view.findViewById(R.idChartFragment.Chart);
            chart = new LineChart(dataset, renderer);

            graphicalView = new GraphicalView(getActivity(), chart);
            renderer.setSelectableBuffer(11);

            layout.addView(graphicalView);
        } else {
            graphicalView.repaint();
        }

        return v;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        avenirHeavy = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Heavy.ttf");
        avenirLight = Typeface.createFromAsset(getActivity().getAssets(), "fonts/Avenir Light.ttf");

        graphicalView.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                SeriesSelection seriesSelection = graphicalView.getCurrentSeriesAndPoint();
                double[] xy = graphicalView.toRealPoint(0);
                //creating the views
                createOnClickPointsView();

                if (seriesSelection != null) {

                    //                  debug
                    Log.d("Punto", seriesSelection.getXValue() + ", " + seriesSelection.getValue());

                    double x = firstSeries.getX(seriesSelection.getPointIndex() + 1);
                    double y = firstSeries.getY(seriesSelection.getPointIndex() + 1);
                    double[] screenPoint = chart.toScreenPoint(new double[] { x, y });

                    //                  debug
                    Log.d("Chart point", "Chart element in series index " + seriesSelection.getSeriesIndex() + " data point index "
                            + seriesSelection.getPointIndex() + " was clicked" + " closest point value X=" + seriesSelection.getXValue()
                            + ", Y=" + seriesSelection.getValue() + " clicked point value X=" + (float) xy[0] + ", Y=" + (float) xy[1]);
                    Log.d("Punto pantalla", " (" + screenPoint[0] + ", " + screenPoint[1] + ")");

                    int value = Integer.parseInt(days.get((int) (days.size() - (13 - x))).getValue());
                    String date = days.get((int) (days.size() - (13 - x))).getDate();
                    pointNumberText.setText(value + "");
                    pointDateText.setText(date);

                    //                  drawing point info
                    absoluteLayout.addView(pointInfoConatiner, new LayoutParams(getResources().getDrawable(R.drawable.graficapin)
                            .getIntrinsicWidth(), getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight(),
                            (int) (screenPoint[0] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicWidth() / 2)),
                            (int) (screenPoint[1] - (getResources().getDrawable(R.drawable.graficapin).getIntrinsicHeight()))));

                    //                  drawing point clicked
                    absoluteLayout.addView(point, new LayoutParams(getResources().getDrawable(R.drawable.puntoon).getIntrinsicWidth(),
                            getResources().getDrawable(R.drawable.puntoon).getIntrinsicHeight(), (int) (screenPoint[0] - (getResources()
                                    .getDrawable(R.drawable.puntoon).getIntrinsicWidth() / 2)), (int) (screenPoint[1] - ((getResources()
                                    .getDrawable(R.drawable.puntoon).getIntrinsicHeight()) / 4))));
                }
            }
        });

    }

    /**
     * Method for set the style of the plotter window and the string at the x
     * axis
     * 
     * @param mRenderer
     *            render to put style in
     * 
     * @param dataSetX
     *            string to set at x axis
     */
    private void setRendererStyling(XYMultipleSeriesRenderer mRenderer) {
        mRenderer.setApplyBackgroundColor(false);
        mRenderer.setMarginsColor(R.drawable.transperent_color);
        mRenderer.setMargins(new int[] { 0, 0, 0, 0 });
        mRenderer.setShowAxes(false);
        mRenderer.setZoomButtonsVisible(false);
        mRenderer.setExternalZoomEnabled(false);
        mRenderer.setPointSize(getResources().getInteger(R.integer.chart_fragment_point_size));
        mRenderer.setClickEnabled(true);
        mRenderer.setDisplayValues(false);
        mRenderer.setXLabels(0);
        mRenderer.setYLabels(0);
        mRenderer.setPanEnabled(true);
        mRenderer.setZoomEnabled(false);
        mRenderer.setShowLegend(false);
        mRenderer.setYAxisMax(max + 10);
        mRenderer.setYAxisMin(min - 10);
    }

    /**
     * Method to introduce the values of the y axis
     * 
     * @param dataSetY
     *            data to set at axis y
     * @return the data to set
     */
    private XYMultipleSeriesDataset getDataset(ArrayList<Day> days) {

        XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
        firstSeries = new XYSeries("");

        for (int i = 0; i < 12; i++) {

            int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());
            firstSeries.add(i, value);

        }
        dataset.addSeries(firstSeries);

        XYSeries secondSeries = new XYSeries("");
        for (int i = 1; i < 11; i++) {

            int value = Integer.parseInt(days.get(days.size() - (13 - i)).getValue());

            if (i == 1) {
                max = value;
                min = value;
            }

            if (value > max)
                max = value;
            if (value < min)
                min = value;

            secondSeries.add(i, value);

        }

        dataset.addSeries(secondSeries);
        return dataset;
    }

    /**
     * Method for set the style of the line you want to plot and create a new
     * renderer
     * 
     * @return the renderer
     */
    private XYMultipleSeriesRenderer getRenderer() {
        XYMultipleSeriesRenderer renderer = new XYMultipleSeriesRenderer();

        //First chart with the line
        XYSeriesRenderer r = new XYSeriesRenderer();
        r.setColor(getResources().getColor(R.color.grey_number_label_background));
        r.setLineWidth(getResources().getInteger(R.integer.chart_fragment_line_width));
        // r.setDisplayChartValues(true);
        r.setPointStyle(PointStyle.POINT);
        r.setFillPoints(true);
        renderer.addSeriesRenderer(r);

        //      Second chart with the points
        XYSeriesRenderer r1 = new XYSeriesRenderer();
        r1.setColor(getResources().getColor(R.color.purple_chart_points));
        r1.setLineWidth(0);
        r1.setFillPoints(true);
        r1.setPointStyle(PointStyle.CIRCLE);
        renderer.addSeriesRenderer(r1);

        return renderer;
    }

    public XYSeries getFirstSeries() {
        return firstSeries;
    }

    public void setFirstSeries(XYSeries firstSeries) {
        this.firstSeries = firstSeries;
    }

    public XYChart getChart() {
        return chart;
    }

    public void setChart(XYChart chart) {
        this.chart = chart;
    }

    /**
     * Method for create the views when clicking on a point of the chart
     */
    private void createOnClickPointsView() {
        //If the info is already visible 
        if (pointInfoConatiner != null)
            absoluteLayout.removeView(pointInfoConatiner);
        //              If the point is drawn
        if (point != null)
            absoluteLayout.removeView(point);

        pointInfoConatiner = new LinearLayout(getActivity());
        pointInfoConatiner.setBackgroundDrawable(getResources().getDrawable(R.drawable.graficapin));
        pointInfoConatiner.setOrientation(LinearLayout.VERTICAL);
        pointInfoConatiner.setGravity(Gravity.CENTER_HORIZONTAL);

        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);
        layoutParams.setMargins(0, 8, 0, 0);

        pointNumberText = new TextView(getActivity());
        pointNumberText.setTextSize(18);
        pointNumberText.setTextColor(getResources().getColor(R.color.purple_chart_points));
        pointNumberText.setTypeface(avenirHeavy);
        pointNumberText.setGravity(Gravity.CENTER);

        pointNameText = new TextView(getActivity());
        pointNameText.setTextSize(18);
        pointNameText.setTextColor(getResources().getColor(R.color.grey_users_label));
        pointNameText.setTypeface(avenirLight);
        pointNameText.setText(metricName);
        pointNameText.setGravity(Gravity.CENTER);

        pointDateText = new TextView(getActivity());
        pointDateText.setTextSize(11);
        pointDateText.setTextColor(getResources().getColor(R.color.grey_users_label));
        pointDateText.setTypeface(avenirHeavy);
        pointDateText.setGravity(Gravity.CENTER);

        pointInfoConatiner.addView(pointNumberText, 0, layoutParams);
        layoutParams.setMargins(0, 2, 0, 0);
        pointInfoConatiner.addView(pointNameText, 1, layoutParams);
        pointInfoConatiner.addView(pointDateText, 2, layoutParams);

        point = new ImageView(getActivity());
        point.setImageDrawable(getResources().getDrawable(R.drawable.puntoon));
    }
}

Anyone know how can I:

1-Quit the bottom border

2-Quit the line of the pink chart

3-The chart don't move when I touch the points

4- When I ask for the screen point why to many times the y value returns infinite

1条回答
beautiful°
2楼-- · 2020-02-14 05:28

There used to be this bug in an older version of AChartEngine. I suggest you update to 1.1.0.

Also, please note that the chart must have been already displayed when calling the method. If the chart didn't display on screen then there is no way to calculate that.

查看更多
登录 后发表回答