Android:绘制同心圆

时间:2017-11-18 06:39:56

标签: android android-canvas surfaceview

我正在尝试编写一个连接到远程主机的应用程序,并读取x,y元组的行,并将它们实时绘制到散点图中。数据正在按预期显示,但是当我修改代码以尝试显示某些标记来测量数据时,它并没有按预期工作。我希望看到一个带有20个同心灰色圆圈的黑色背景。当数据卷入其中时,应在同心圆上显示为绿点。相反,我在远程主机关闭时看到的是调用initializeSurface()并且仅显示外部灰色圆圈(i = 20)。并且,当远程主机向上初始化时,调用drawPoint()跟随的快速跟随(),并且不显示灰色圆圈,只显示绿色圆点。代码如下,接着是之前描述的2个屏幕截图。

package com.balaguru.ggdiagram;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;

class ToastThread implements Runnable {
    private String ivMessage;
    private View ivView;
    ToastThread(View pView, String pMessage) { ivView = pView; ivMessage = pMessage; }
    public void run() {
        Toast.makeText(ivView.getContext(), ivMessage, Toast.LENGTH_LONG).show();
    }
}
class ConnectionThread extends Thread {

    private GGView ivGGView;

    ConnectionThread(GGView pGGView) {
        ivGGView = pGGView;
    }

    public void run() {
        try {
            ivGGView.initializeSurface();
            //Toast.makeText(MainActivity.context, "office-main", Toast.LENGTH_LONG).show();
            Socket socket = new Socket("192.168.1.197", 10000);
            BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String line = input.readLine();
            while (line != null) {
                if (line.equals("not connected")) {
                    ivGGView.drawPoint(0, 0, Color.GREEN);
                } else {
                    String[] gg = line.split(",");
                    float x = Float.parseFloat(gg[0]);
                    float y = Float.parseFloat(gg[1]);
                    ivGGView.drawPoint(x, y, Color.GREEN);
                }
                line = input.readLine();
            }
        } catch (Throwable e) {
            StringWriter error = new StringWriter();
            e.printStackTrace(new PrintWriter(error));
            ToastThread toast = new ToastThread(ivGGView, error.toString());
            Activity activity = (Activity) ivGGView.getContext();
            activity.runOnUiThread(toast);
        }
    }
}

class GGView extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder ivHolder;
    public Context ivContext;
    private int ivWidth;
    private int ivHeight;

    public GGView(Context context){
        super(context);
        ivContext = context;
        ivHolder = getHolder();
        ivHolder.addCallback(this);
    }
    public void surfaceDestroyed(SurfaceHolder pHolder) {}
    public void surfaceCreated(SurfaceHolder pHolder) {
        ConnectionThread thread = new ConnectionThread(this);
        thread.start();
    }
    public void surfaceChanged(SurfaceHolder pHolder, int pFormat, int pWidth, int pHeight) {}

    public void initializeSurface() {
        Canvas canvas = ivHolder.lockCanvas();
        ivWidth = canvas.getWidth();
        ivHeight = canvas.getHeight();
        canvas.drawColor(Color.BLACK);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.GRAY);
        paint.setStrokeWidth(4);
        paint.setStyle(Paint.Style.STROKE);
        for (int i = 1; i <= 20; i++) {
            canvas.drawArc(ivWidth/2 - i/20*ivHeight/2,
                ivHeight/2 - i/20*ivHeight/2,
                ivWidth/2 + i/20*ivHeight/2,
                ivHeight/2 + i/20*ivHeight/2,
                0, 360, false, paint);
        }
        ivHolder.unlockCanvasAndPost(canvas);
    }

    public void drawPoint(float pX, float pY, int pColor) {
        float x = pX / 20 * ivHeight/2 + ivWidth/2;
        float y = pY / 20 * ivHeight/2 + ivHeight/2;
        Canvas canvas = ivHolder.lockCanvas(
                new Rect((int) x-4, (int)y-4, (int) x+4, (int)y+4));
        Paint paint = new Paint();
        paint.setColor(pColor);
        paint.setStrokeWidth(4);
        canvas.drawPoint(x, y, paint);
        ivHolder.unlockCanvasAndPost(canvas);

    }
}


public class MainActivity extends Activity {

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        GGView ggView = new GGView(this);
        setContentView(ggView);
    }

}

enter image description here enter image description here

修改 如果我在initializeSurface()中将for循环更改为20到40,那么当i = 20且i = 40但是没有其他时,drawArc似乎绘制同心圆。屏幕截图如下。

enter image description here

1 个答案:

答案 0 :(得分:0)

发现问题:i / 20正在进行整数除法,并在绘制弧时评估为0。将其更改为i / 10f修复了该问题。 20f画了太多圈子。 lockCanvas()返回一些缓冲画布中的一个,我只是在其中一个画布上绘制我的圆圈。结果,我后来对drawPoint()的调用正在绘制画布而没有绘制那些圆圈。为了解决这个问题,我不得不调用lockCanvas()3次并将我的圆圈绘制到每个。这不是一个非常优雅的解决方案,但似乎有效。更正了以下代码:

    public void initializeSurface() {
        for (int j = 0; j <= 3; j++) {
            Canvas canvas = ivHolder.lockCanvas();
            ivWidth = canvas.getWidth();
            ivHeight = canvas.getHeight();
            canvas.drawColor(Color.BLACK);
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setColor(Color.GRAY);
            paint.setStrokeWidth(4);
            paint.setStyle(Paint.Style.STROKE);
            Paint font = new Paint();
            font.setTextSize(16);
            font.setColor(Color.WHITE);
            float width = ivWidth;
            float height = ivHeight;
            for (int i = 1; i <= 10; i++)
                canvas.drawCircle(width / 2, height / 2, i / 10f * height / 2f, paint);
            ivHolder.unlockCanvasAndPost(canvas);
        }
    }

enter image description here