Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
893 views
in Technique[技术] by (71.8m points)

android - achartengine toScreenPoint(double) always returns nullPointerException

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 (applicat

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...