I'm a beginner in Android and I try to scale the chart in my application, but the code I wrote below doesn't work due to error:
java.lang.NullPointerException: Attempt to invoke virtual method (android.view.View$OnTouchListener)' on a null object reference.
I have no idea, how I could correct it in my code.
Thank in advance for help.
public class EcgChartActivity extends Activity implements OnTouchListener
{
private PointF minXY;
private PointF maxXY;
//Class updating the data on the chart
private class EcgUpdater implements Observer {
private final Plot plot;
public EcgUpdater(Plot plot) {
this.plot = plot;
}
@Override
public void update(Observable arg0, Object arg1) {
plot.redraw();
}
}
private XYPlot ecgPlot;
private EcgUpdater ecgUpdater;
private Thread ecgPlotThread;
private LinkedHashMap<Integer, ChannelData> allChannelsData;
private EcgDataSource ecgDataSource;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ecg_chart);
this.ecgPlot = (XYPlot) findViewById(R.id.ecg_plot);
this.ecgUpdater = new EcgUpdater(this.ecgPlot);
this.ecgDataSource = BaseApp.getApp().getEcgDataSource();
this.ecgPlotThread = new Thread(this.ecgDataSource);
ecgPlot.setOnTouchListener(this);
ecgPlot.getGraphWidget().setTicksPerRangeLabel(1);
ecgPlot.getGraphWidget().setTicksPerDomainLabel(1);
ecgPlot.getGraphWidget().setRangeValueFormat(
new DecimalFormat("#######"));
ecgPlot.getGraphWidget().setDomainValueFormat(
new DecimalFormat("#######"));
ecgPlot.getGraphWidget().setRangeLabelWidth(25);
ecgPlot.setRangeLabel("");
ecgPlot.setDomainLabel("");
//Adding series to chart
EcgPlotSeries channel1 = new EcgPlotSeries(this.ecgDataSource, 0, "Channel 1", Color.RED);
this.ecgPlot.addSeries(channel1, channel1.getFormatter());
EcgPlotSeries channel2 = new EcgPlotSeries(this.ecgDataSource, 1, "Channel 2", Color.BLUE);
this.ecgPlot.addSeries(channel2, channel2.getFormatter());
ecgPlot.redraw();
ecgPlot.calculateMinMaxVals();
minXY=new PointF(ecgPlot.getCalculatedMinX().floatValue(),ecgPlot.getCalculatedMinY().floatValue());
maxXY=new PointF(ecgPlot.getCalculatedMaxX().floatValue(),ecgPlot.getCalculatedMaxY().floatValue());
BaseApp.getApp().getEcgDataSource().addObserver(this.ecgUpdater);
}
// Definition of the touch states
static final int NONE = 0;
static final int ONE_FINGER_DRAG = 1;
static final int TWO_FINGERS_DRAG = 2;
int mode = NONE;
PointF firstFinger;
float lastScrolling;
float distBetweenFingers;
float lastZooming;
@Override
public void onResume() {
// Uruchomienie wątku rysującego wykres
this.ecgPlotThread.start();
super.onResume();
}
@Override
public void onPause() {
BaseApp.getApp().getEcgDataSource().stopThread();
super.onPause();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
firstFinger = new PointF(event.getX(), event.getY());
mode = ONE_FINGER_DRAG;
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
while(Math.abs(lastScrolling)>1f || Math.abs(lastZooming-1)<1.01){
lastScrolling*=.8;
scroll(lastScrolling);
lastZooming+=(1-lastZooming)*.2;
zoom(lastZooming);
ecgPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
ecgPlot.redraw();
}
}
}, 0);
break;
case MotionEvent.ACTION_POINTER_DOWN:
distBetweenFingers = spacing(event);
if (distBetweenFingers > 5f) {
mode = TWO_FINGERS_DRAG;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == ONE_FINGER_DRAG) {
PointF oldFirstFinger=firstFinger;
firstFinger=new PointF(event.getX(), event.getY());
lastScrolling=oldFirstFinger.x-firstFinger.x;
scroll(lastScrolling);
lastZooming=(firstFinger.y-oldFirstFinger.y)/ecgPlot.getHeight();
if (lastZooming<0)
lastZooming=1/(1-lastZooming);
else
lastZooming+=1;
zoom(lastZooming);
ecgPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
ecgPlot.redraw();
} else if (mode == TWO_FINGERS_DRAG) {
float oldDist =distBetweenFingers;
distBetweenFingers=spacing(event);
lastZooming=oldDist/distBetweenFingers;
zoom(lastZooming);
ecgPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
ecgPlot.redraw();
}
break;
}
return true;
}
private void zoom(float scale) {
float domainSpan = maxXY.x - minXY.x;
float domainMidPoint = maxXY.x - domainSpan / 2.0f;
float offset = domainSpan * scale / 2.0f;
minXY.x=domainMidPoint- offset;
maxXY.x=domainMidPoint+offset;
}
private void scroll(float pan) {
float domainSpan = maxXY.x - minXY.x;
float step = domainSpan / ecgPlot.getWidth();
float offset = pan * step;
minXY.x+= offset;
maxXY.x+= offset;
}
@SuppressLint("FloatMath")
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
}
Log:
12-09 21:39:40.893: E/AndroidRuntime(3137): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.ecganalyzer/com.example.ecganalyzer.activities.EcgChartActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.androidplot.xy.XYPlot.setOnTouchListener(android.view.View$OnTouchListener)' on a null object reference
12-09 21:39:40.893: E/AndroidRuntime(3137):at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2391)
12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.ActivityThread.access$800(ActivityThread.java:151)
12-09 21:39:40.893: E/AndroidRuntime(3137):at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1309)
12-09 21:39:40.893: E/AndroidRuntime(3137): at android.os.Handler.dispatchMessage(Handler.java:102)
12-09 21:39:40.893: E/AndroidRuntime(3137): at android.os.Looper.loop(Looper.java:135)
12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.ActivityThread.main(ActivityThread.java:5349)
12-09 21:39:40.893: E/AndroidRuntime(3137): at java.lang.reflect.Method.invoke(Native Method)
12-09 21:39:40.893: E/AndroidRuntime(3137): at java.lang.reflect.Method.invoke(Method.java:372)
12-09 21:39:40.893: E/AndroidRuntime(3137): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
12-09 21:39:40.893: E/AndroidRuntime(3137): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
12-09 21:39:40.893: E/AndroidRuntime(3137): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.androidplot.xy.XYPlot.setOnTouchListener(android.view.View$OnTouchListener)' on a null object reference
12-09 21:39:40.893: E/AndroidRuntime(3137): at com.example.ecganalyzer.activities.EcgChartActivity.onCreate(EcgChartActivity.java:112)12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.Activity.performCreate(Activity.java:6020) 12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)12-09 21:39:40.893: E/AndroidRuntime(3137): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2284)12-09 21:39:40.893: E/AndroidRuntime(3137): ... 10 more