Pergunta

I want to have an app that shows me a textview and a line chart dynamically updated with the values that I receive from a range sensor. I used a modified TextView which manages the messages and it works well. I tried to do the same thing with a GraphicalView from AChartEngine, but the Chart doesn't change with the arrival of new messages.

Here is my code, any suggestion or advice?

public class NxtActivity extends RosActivity{


private XYSeries mCurrentSeries = new XYSeries("range data series");
private XYSeriesRenderer mCurrentRenderer = new XYSeriesRenderer();
private XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();
private XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();

private LineChart linec;
private Canvas canvas = new Canvas();
private RosChartView<std_msgs.String> rdrawview;

private RosTextView<std_msgs.String> rosTextView;
private Android_Talker talker;
 private java.net.URI master_uri;

//costruttore
public NxtActivity() {
    // The RosActivity constructor configures the notification title and ticker
    // messages.
        super("Pubsub Tutorial mod", "Pubsub Tutorial mod");

  }


@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_nxt);
//setto i parametri del renederer relativo alla singola seria
mCurrentRenderer.setPointStyle(PointStyle.CIRCLE);
mCurrentRenderer.setFillPoints(true);
mCurrentRenderer.setLineWidth(2);
//setto i parametri del renderer globale
mRenderer.addSeriesRenderer(mCurrentRenderer);
  mRenderer.setApplyBackgroundColor(true);
    mRenderer.setBackgroundColor(Color.argb(100, 50, 50, 50));
    mRenderer.setAxisTitleTextSize(16);
    mRenderer.setChartTitleTextSize(20);
    mRenderer.setLabelsTextSize(15);
    mRenderer.setLegendTextSize(15);
    mRenderer.setMargins(new int[] { 20, 30, 15, 0 });
    mRenderer.setZoomButtonsVisible(true);
    mRenderer.setPointSize(10);
mRenderer.setXTitle("time");
mRenderer.setYTitle("ranges");
//setto la serie
mCurrentSeries.add(1,1);
//setto il dataset
    mDataset.addSeries(mCurrentSeries);
//setto LineChart
    linec = new LineChart(mDataset,mRenderer);
//inizializzo RosChartView
    rdrawview=new RosChartView<std_msgs.String>(this,linec,canvas);
rdrawview.setTopicName("chatter_nxt");
   rdrawview.setMessageType(std_msgs.String._TYPE);
rdrawview.setMessageToStringCallable(new MessageCallable<String, std_msgs.String>() {
           @Override
          public String call(std_msgs.String message) {          
    return message.getData();
          }
      });
    //assegno RosChartView al Layout corrispondente
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
layout.addView(rdrawview, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
rdrawview.repaint();
//rdrawview.setup(3,3);

 rosTextView = (RosTextView<std_msgs.String>) findViewById(R.id.text1);
    rosTextView.setTopicName("chatter_nxt");
    rosTextView.setMessageType(std_msgs.String._TYPE);

 rosTextView.setMessageToStringCallable(new MessageCallable<String, std_msgs.String>() {
           @Override
          public String call(std_msgs.String message) {          
    return message.getData();
          }
      });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   getMenuInflater().inflate(R.menu.activity_nxt, menu);
    return true;
}


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        //case android.R.id.home:
         //   NavUtils.navigateUpFromSameTask(this);
          //  return true;
    }
    return super.onOptionsItemSelected(item);
}

@Override
protected void init(NodeMainExecutor nodeMainExecutor) {
talker = new Android_Talker();
NodeConfiguration nodeConfiguration = NodeConfiguration.newPrivate();
// At this point, the user has already been prompted to either enter the URI
// of a master to use or to start a master locally.
try {

    master_uri  = new java.net.URI("http://150.145.11.98:11311");
 nodeConfiguration.setMasterUri(master_uri);
}
catch(URISyntaxException e){
System.out.println("URI is a malformed URL");
}
rdrawview.setup(3,3);
nodeConfiguration.setMasterUri(master_uri);
nodeMainExecutor.execute(talker, nodeConfiguration);
// The RosTextView is also a NodeMain that must be executed in order to
// start displaying incoming messages.
nodeMainExecutor.execute(rosTextView, nodeConfiguration);
nodeMainExecutor.execute(rdrawview, nodeConfiguration);
}

}

Modified textview:

    public class RosTextView<T> extends TextView implements NodeMain {

  private String topicName;
  private String messageType;
    private int count=0;
  private MessageCallable<String, T> callable;

  public RosTextView(Context context) {
    super(context);
  }

  public RosTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  public RosTextView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  public void setTopicName(String topicName) {
    this.topicName = topicName;
  }

  public void setMessageType(String messageType) {
    this.messageType = messageType;
  }

  public void setMessageToStringCallable(MessageCallable<String, T> callable) {
    this.callable = callable;
  }

  @Override
  public GraphName getDefaultNodeName() {
    return GraphName.of("android_gingerbread/ros_text_view");
  }

  @Override
  public void onStart(ConnectedNode connectedNode) {
    Subscriber<T> subscriber = connectedNode.newSubscriber(topicName, messageType);
    subscriber.addMessageListener(new MessageListener<T>() {
      @Override
      public void onNewMessage(final T message) {
        if (callable != null) {
          post(new Runnable() {
            @Override
            public void run() {
              setText(callable.call(message));
        count++;
        if((count%2)==0){setTextColor(Color.RED);}
        else{setTextColor(Color.BLUE);}
            }
          });
        } else {
          post(new Runnable() {
            @Override
            public void run() {
              setText(message.toString());
            }
          });
        }
        postInvalidate();
      }
    });
  }

  @Override
  public void onShutdown(Node node) {
  }

  @Override
  public void onShutdownComplete(Node node) {
  }

  @Override
  public void onError(Node node, Throwable throwable) {
  }
}

Modifed graphicalview:

   public class RosChartView<T> extends GraphicalView implements NodeMain {
    //---------
  private XYMultipleSeriesDataset mDataset = new XYMultipleSeriesDataset();
  private XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
  private XYSeries mCurrentSeries = new XYSeries("range data series");
  private int x;
  private int y;
  Context context;
  Canvas canvas; 
    //---------
  private String topicName;
  private String messageType;
  private int count=0;
  private MessageCallable<String, T> callable;

  public RosChartView(Context context, LineChart xyc, Canvas canvas_) {
    super(context,xyc);
    this.context=context;
    mDataset = xyc.getDataset();    
    mRenderer = xyc.getRenderer();
    mRenderer.setClickEnabled(true);
        mRenderer.setSelectableBuffer(100);
    x=0;
    y=0;
    canvas=canvas_;



  }

  public RosChartView(Context context, AttributeSet attrs, LineChart xyc) {

    super(context, xyc);
    mDataset = xyc.getDataset();    
    mRenderer = xyc.getRenderer();
    mRenderer.setClickEnabled(true);
        mRenderer.setSelectableBuffer(100);
    x=0;
    y=0;


  }

  public RosChartView(Context context, AttributeSet attrs, int defStyle, LineChart xyc) {
    super(context, xyc);

    mDataset = xyc.getDataset();    
    mRenderer = xyc.getRenderer();
    mRenderer.setClickEnabled(true);
        mRenderer.setSelectableBuffer(100);
    x=0;
    y=0;
  }

  public void setTopicName(String topicName) {
    this.topicName = topicName;
  }

  public void setMessageType(String messageType) {
    this.messageType = messageType;
  }

  public void setMessageToStringCallable(MessageCallable<String, T> callable) {
    this.callable = callable;
  }

  @Override
  public GraphName getDefaultNodeName() {
    return GraphName.of("android_gingerbread/ros_text_view");
  }

  @Override
  public void onStart(ConnectedNode connectedNode) {
    Subscriber<T> subscriber = connectedNode.newSubscriber(topicName, messageType);
    subscriber.addMessageListener(new MessageListener<T>() {
      @Override
      public void onNewMessage(final T message) {
        if (callable != null) {
          post(new Runnable() {
            @Override
            public void run() {
        count++;
        x=count;
        y=Integer.parseInt(callable.call(message));
        XYSeries series=new XYSeries("new_series");
        series=mCurrentSeries;
        series.add(2,2);
        mDataset.removeSeries(mCurrentSeries);
        mCurrentSeries=series;
        mDataset.addSeries(mCurrentSeries);
                repaint();
            }
          });
        } else {
          post(new Runnable() {
            @Override
            public void run() {
          count++;
          x=count;
              y=Integer.parseInt(message.toString());
          mCurrentSeries.add(x,y);

            }
          });
        }
        postInvalidate();
      }
    });
  }

  @Override
  public void onShutdown(Node node) {
  }

  @Override
  public void onShutdownComplete(Node node) {
  }

  @Override
  public void onError(Node node, Throwable throwable) {
  }

  public void setup(double x,double y)
  {

        mCurrentSeries.add(x,y);          
          this.repaint();

   }
}

layout

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:tools="http://schemas.android.com/tools"

        android:layout_width="match_parent"

        android:layout_height="match_parent" >





       <org.ros.android.view.RosTextView
        android:id="@+id/text1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30dip" 
    />

    <LinearLayout
    android:id="@+id/chart"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:layout_below="@id/text1"
    android:orientation="horizontal" />



    </RelativeLayout>
Foi útil?

Solução

When a message is received, you do the following:

    XYSeries series=new XYSeries("new_series");
    series=mCurrentSeries;
    series.add(2,2);
    mDataset.removeSeries(mCurrentSeries);
    mCurrentSeries=series;
    mDataset.addSeries(mCurrentSeries);

This means that you create a new series, then the reference to the current series is given to the variable that was previously created as new series then you add a point at location 2, 2 then you remove the series and add it back. This is totally wrong.

The following should be sufficient:

mCurrentSeries.add(x, y); // NOT 2, 2
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top