Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在不同类中使用Android画布,调试崩溃错误_Java_Android_Canvas - Fatal编程技术网

Java 在不同类中使用Android画布,调试崩溃错误

Java 在不同类中使用Android画布,调试崩溃错误,java,android,canvas,Java,Android,Canvas,从Android、canvas和作品开始。我有可以在图形对象上绘制形状的现有Java代码。我正试图在一个带有Canvas的Android应用程序中使用该代码。基本上,我试图避免重构所有Java代码以显式使用Canvas。所以我正在制作我自己的“图形”对象。它所要做的就是调用适当的Canvas方法来绘制指定的形状 我在这里读过多篇关于不能在onDraw()方法之外使用canvas对象的文章。据我所知,您不能将canvas对象传递给其他类并期望它正常工作。但我也不完全了解这一切是如何运作的 应用程序

从Android、canvas和作品开始。我有可以在图形对象上绘制形状的现有Java代码。我正试图在一个带有Canvas的Android应用程序中使用该代码。基本上,我试图避免重构所有Java代码以显式使用Canvas。所以我正在制作我自己的“图形”对象。它所要做的就是调用适当的Canvas方法来绘制指定的形状

我在这里读过多篇关于不能在
onDraw()
方法之外使用canvas对象的文章。据我所知,您不能将canvas对象传递给其他类并期望它正常工作。但我也不完全了解这一切是如何运作的

应用程序在drawOval方法的Graphics类中崩溃。我已经读了一本关于所有这些的日志,但是我还没有找到一个好的答案来解释为什么这不起作用。 我还没有找到一种方法以java友好的方式获取崩溃日志(也称为stacktrace)。它只是在tid 1520中抛出致命信号11(SIGSEGV)、代码1、故障地址0x130

谢谢!如果需要更多细节,请告诉我。这是我的密码:

main活动

public class MainActivity extends AppCompatActivity {

    MyCanvas canvas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        canvas = new MyCanvas(this);
        setContentView(canvas);
    }
}
MyCanvas视图

public class MyCanvas extends View {
    Graphics graphics;
    List<Shape> shapes;

    public MyCanvas(Context context) {
        super(context);
        graphics = new Graphics();
        shapes = new ArrayList<>();
    }

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        graphics.setCanvas(canvas); //Sets the canvas object in the graphics class
        for (Shape shape : shapes) {
            try { //this is in a try/catch block for custom exception handling
                //This just calls the specific shapes render method,
                //in this case, a circle from the makeShape Method
                //The graphics object then calls the specific shape to
                //render on the canvas
                shape.render(graphics, 0, 0); 
            } catch (ShapeException e) {
                e.printStackTrace();
            }
        }
        invalidate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                int x = (int) event.getX();
                int y = (int) event.getY();
                try { //this is in a try/catch block for custom exception handling
                    makeShape(x, y);
                } catch (ShapeException e) {
                    e.printStackTrace();
                }
                invalidate();

            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL: {
                break;
            }
        }
        invalidate();
        return true;
    }

    public void makeShape(int x, int y) throws ShapeException{
        Point p = new Point(x, y);
        Shape shape = new Circle(p, 50, 50);
        shapes.add(shape);
    }

}

您对能够将
画布
传递给不同的类有一点误解。这绝对没有错,;将画布传递给类方法实际上与将其传递给常规函数相同。即使将
Canvas
引用存储在成员变量中也不会有任何影响

但是,只有在理解到
Canvas
不能在
draw()
/
onDraw()
方法的范围之外使用时,上述内容才是正确的。也就是说,任何使用
Canvas
的方法都必须从
onDraw()
中调用,或者从
onDraw()调用的函数中调用

这是因为
Canvas
是在
onDraw()
之前初始化的(由框架),以便为当前绘图操作做好准备。您可能希望将其视为使用
位图
初始化
画布
,该位图将用作此特定屏幕框的绘图输出面(这与事实并不遥远)。返回
onDraw()
后,框架将假定您的代码不再使用它,并且它可以将输出表面/
位图
/等提交给屏幕合成器进行渲染,而无需担心进一步的修改

而且,您的方法是一种很好的方法,它是一种调整现有代码以使用新图形对象的技术


因此,为了解决这个问题:在正常的Android开发中,当您不(直接)处理本机/JNI例程时,SIGSEGVs不应该发生。但是,我突然想到,如果
Canvas
对象发生更改,您不会更新它。这可能会导致崩溃(在本机代码中,这就是为什么您没有获得Java堆栈跟踪)。在给您一张较新的画布之后,您使用了一张旧的
画布。如果(this.canvas==null)删除条件
,您应该会没事。

好的,是的,您肯定确认了我对它的一些想法。我认为使用其他地方的
Canvas
会引起问题。基本上,流程从我的
onDraw
方法,到我自己的Java
Shape
代码,其中有一个渲染方法,它接受一个
Graphics
对象。然后通过调用
graphics.drawOval()
使用该图形对象,就像使用JavaAWT一样。因为我不能使用它,所以我正在创建自己的图形类,它只接收调用
canvas.drawCircle()
所需的参数。所以除此之外,我没有使用任何其他第三方库。@pianoman102抱歉,刚刚更新了我的答案。请重新阅读最后一段:)经过一些调试,我确信在我的图形类中执行
canvas.drawCircle()
后它会崩溃。哦,我现在明白了。所以每次调用
onDraw()
时它都是一个新的画布对象?这是为什么,又是如何起作用的?对我来说,这似乎是一个很大的重复。@pianoman102我不确定框架每次提供不同画布对象的确切原因。但是,它相当轻;只是
位图
视图
(或视图树)之间的绑定。只是b/c你得到了一个新的
画布
,并不意味着有很多重新渲染,但是你可能会惊讶地知道,事实上,Android每次都会重新渲染整个视图,即使是最小的更改(通常)。没有太多的阐述,这是因为它简化了
onDraw()
实现、合成、alpha混合以及基于硬件的表面使用的细节。
public class Graphics {
    private Canvas canvas = null;

    public Graphics() {
    }

    public void setCanvas(Canvas canvas) {
        if (this.canvas == null) {
            this.canvas = canvas;
        }
    }

    public void drawOval(int x, int y, int width, int height) {
        Paint paint1 = new Paint();
        paint.setColor(Color.BLACK);
        canvas.drawCircle(500, 500, 50, paint1); //App crashes here
    }
}