简体   繁体   English

Android-如何从另一个类调用invalidate()方法?

[英]Android - How do I call invalidate() method from another class?

I need to call invalidate() method from my MainActivity class. 我需要从MainActivity类中调用invalidate()方法。 I can call it from my CanvasView class, but from MainActivity, it gives me an error. 我可以从CanvasView类中调用它,但是从MainActivity中,它给我一个错误。 Says invalidate is non-static method. 说无效是非静态方法。 How do I get past this? 我该如何克服? I have searched and tried some solutions, but haven't got it to work. 我已经搜索并尝试了一些解决方案,但是还没有成功。

I want to delete drawn items from the screen, but when I select Undo from menu list, it won't update the screen. 我想从屏幕上删除绘制的项目,但是当我从菜单列表中选择“撤消”时,它不会更新屏幕。 Only when I touch the screen, it Undos elements. 仅当我触摸屏幕时,它才会撤消元素。

My CanvasView class 我的CanvasView类

package com.example.HW3;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
 * Android Kimp.
 * @author Martin
 *
 */
public class CanvasView extends View {
/**
 * Rectangles.
 */
    private Rect rectangle = new Rect();
/**
 * These help calculating rectangle coordinates.
 */
    private float d1 = 0, d2 = 0;
/**
 * Canvas.
 */
    private Canvas canvas = new Canvas();
/**
 *  Paint to draw shapes.
 */
    private Paint paint = new Paint();
    /**
     *  Paint to draw shapes.
     */
    private Paint paint2 = new Paint();
    /**
     *  Paint to draw shapes.
     */
    private Paint paint3 = new Paint();
    /**
     *  Paint to draw shapes.
     */
    private Paint paint4 = new Paint();
/**
 * Path.
 */
    private Path path = new Path();
/**
 * Point.
 */
    private Point point = new Point();
/**
 * List for lines.
 */
    private static List<Path> lines = new ArrayList<Path>();
    private static List<Path> lines2 = new ArrayList<Path>();
/**
 * List for points.
 */
    private static List<Point> points = new ArrayList<Point>();
    private static List<Point> points2 = new ArrayList<Point>();
/**
 * List for rectangles.
 */
    private static List<Rect> rectangles = new ArrayList<Rect>();
    private static List<Rect> rectangles2 = new ArrayList<Rect>();

    private static List<Integer> elements = new ArrayList<Integer>();
    private static List<Integer> elements2 = new ArrayList<Integer>();
/**
 * Touch coordinates.
 */
    private float x, startX, endX;
/**
 * Touch coordinates.
 */
    private float y, startY, endY;
/**
 * This checks whether user draws a line or a point.
 */

    private int whichShape;

    private boolean touchStarted = false;
/**
 * Enum to hold the value of DrawMode, whether user wants to draw lines or rectangles.
 *
 */
    public enum undoRedo {
        DoUndoRedo, DoNothing
    };

    public static undoRedo currentState = undoRedo.DoNothing;

    public enum DrawMode {
        /**
         * DrawMode possibilities.
         */
        FreeDrawMode, RectDrawMode, SelectAndDrag
    };
/**
 * Sets current DrawMode, when application starts.
 */
    public static DrawMode currentDrawMode = DrawMode.FreeDrawMode;
/**
 * Sets DrawMode.
 * @param newDrawMode
 */
    final Handler handler = new Handler();
    /**
     * Runnable interface to detect long press.
     */
    Runnable mLongPressed = new Runnable() {
        public void run() {
            for (int i = 0; i < getRectangles().size(); i++) {
            Log.i("", "Long press!");
            Rect a = getRectangles().get(i);
            System.out.println(a + " " + i);
            double x = getRectangles().get(i).left;
            System.out.println(a + " " + x);
            currentDrawMode = DrawMode.SelectAndDrag;
        }
        }
    };
/**
 * CanvasView.
 * @param context
 * @param attrs
 */



    public CanvasView(Context context, AttributeSet attrs) {
        super(context, attrs);

        paint.setAntiAlias(true);
        paint.setStrokeWidth(3);
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeJoin(Paint.Join.ROUND);

        paint2.setAntiAlias(true);
        paint2.setStrokeWidth(3);
        paint2.setColor(Color.RED);
        paint2.setStyle(Paint.Style.STROKE);
        paint2.setStrokeJoin(Paint.Join.ROUND);


        paint3.setAntiAlias(true);
        paint3.setColor(Color.BLACK);
        paint3.setStrokeWidth(3);
        paint3.setStyle(Paint.Style.STROKE);
        paint3.setStrokeJoin(Paint.Join.ROUND);

        paint4.setAntiAlias(true);
        paint4.setColor(Color.BLACK);
        paint4.setStrokeWidth(3);
        paint4.setStyle(Paint.Style.STROKE);
        paint4.setShadowLayer(10,5,5,Color.BLACK);
        paint4.setStrokeJoin(Paint.Join.ROUND);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        for (Rect r : getRectangles()) {
            canvas.drawRect(r, paint);
        }
        canvas.drawRect(rectangle, paint3);

        for (Path p : getLines()) {
            canvas.drawPath(p, paint);
        }
        canvas.drawPath(path, paint2);

        for (Point point : getPoints()) {
            canvas.drawCircle(point.x, point.y, 1, paint);
    }
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        x = event.getX();
        y = event.getY();

        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            handler.postDelayed(mLongPressed, 500);
        }
        if ((event.getAction() == MotionEvent.ACTION_MOVE)
            || (event.getAction() == MotionEvent.ACTION_UP)) {
            handler.removeCallbacks(mLongPressed);
        }
        if (currentDrawMode == DrawMode.FreeDrawMode) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // Set new starting point
                paint2.setColor(Color.RED);
                path = new Path();
                path.moveTo(x, y);
                touchStarted = true;
                break;

            case MotionEvent.ACTION_MOVE:
                touchStarted = false;
                path.lineTo(x, y);

                break;
            case MotionEvent.ACTION_UP:
                if (touchStarted) {
                    point = new Point();
                    point.x = (int) x;
                    point.y = (int) y;
                    paint2.setColor(Color.BLACK);
                    whichShape = 1;
                    getElements().add(whichShape);
                    getPoints().add(point);
                    getElements2().clear();
                    touchStarted = false;
                    System.out.println("here");
                } else {
                    System.out.println("there");
                    paint2.setColor(Color.BLACK);
                    whichShape = 2;
                    getElements().add(whichShape);
                    getLines().add(path);
                    getElements2().clear();
                }
                break;
            default:
                return false;
            }
        } else if (currentDrawMode == DrawMode.RectDrawMode) {

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // Set a new starting point
                rectangle = new Rect();
                paint3.setColor(Color.RED);
                startX = event.getX();
                startY = event.getY();
                System.out.println("down");

                break;
            case MotionEvent.ACTION_MOVE:
                endX = event.getX();
                endY = event.getY();
                System.out.println("move");
                System.out.println(startX + " " + endX + " " + startY + " " + endY);

                if (startX >= endX && startY >= endY) {

                    rectangle.set((int) endX, (int) endY, (int) startX,
                            (int) startY);
                    canvas.drawRect(rectangle, paint2);
                } else if (startX >= endX && startY <= endY) {
                    d1 = startX + (endX - startX);

                    d2 = startY + (endY - startY);

                    rectangle.set((int) d1, (int) startY, (int) startX,
                            (int) d2);
                    canvas.drawRect(rectangle, paint3);
                } else if (startX <= endX && startY >= endY) {

                    d1 = startY + (endY - startY);
                    d2 = startX + (endX - startX);

                    rectangle.set((int) startX, (int) d1, (int) d2,
                            (int) startY);
                    canvas.drawRect(rectangle, paint3);
                    System.out.println("olen siin");
                } else {

                    rectangle.set((int) startX, (int) startY, (int) endX,
                            (int) endY);
                    canvas.drawRect(rectangle, paint3);
                }
                break;
            case MotionEvent.ACTION_UP:
                System.out.println("up");
                paint3.setColor(Color.BLACK);
                whichShape = 3;
                getElements().add(whichShape);
                getRectangles().add(rectangle);
                getElements2().clear();
                break;
            default:    
                return false;
            }
        } else if (currentDrawMode == DrawMode.SelectAndDrag) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:


                break;
            case MotionEvent.ACTION_UP:

                break;
            default:
                return false;
            }
        }
        // Makes our view repaint and call onDraw
        invalidate();
        return true;
    }

    public static List<Integer> getElements() {
        return elements;
    }

    public static void setElements(List<Integer> elements) {
        CanvasView.elements = elements;
    }

    public static List<Point> getPoints() {
        return points;
    }

    public static void setPoints(List<Point> points) {
        CanvasView.points = points;
    }

    public static List<Path> getLines() {
        return lines;
    }

    public static void setLines(List<Path> lines) {
        CanvasView.lines = lines;
    }

    public static List<Rect> getRectangles() {
        return rectangles;
    }

    public static void setRectangles(List<Rect> rectangles) {
        CanvasView.rectangles = rectangles;
    }

    public static List<Point> getPoints2() {
        return points2;
    }

    public static void setPoints2(List<Point> points2) {
        CanvasView.points2 = points2;
    }

    public static List<Integer> getElements2() {
        return elements2;
    }

    public static void setElements2(List<Integer> elements2) {
        CanvasView.elements2 = elements2;
    }

    public static List<Path> getLines2() {
        return lines2;
    }

    public static void setLines2(List<Path> lines2) {
        CanvasView.lines2 = lines2;
    }

    public static List<Rect> getRectangles2() {
        return rectangles2;
    }

    public static void setRectangles2(List<Rect> rectangles2) {
        CanvasView.rectangles2 = rectangles2;
    }
}

My MainActivity class 我的MainActivity课程

package com.example.HW3;

import com.example.HW3.CanvasView.undoRedo;
import com.example.androiddrawing.R;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.Window;
import android.view.WindowManager;
/**
 * Android application.
 * @author Martin
 *
 */
public class MainActivity extends Activity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.activity_main);


    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.default_drawing) {
            CanvasView.currentDrawMode = CanvasView.DrawMode.FreeDrawMode;
            return true;
        } else if (id == R.id.draw_rectangle) {
            CanvasView.currentDrawMode = CanvasView.DrawMode.RectDrawMode;
            return true;
        } else if (id == R.id.undo) {
            int listSize = CanvasView.getElements().size();
              System.out.println(CanvasView.getElements().size());
              if (CanvasView.getElements().size() == 0) {
                return true;  
              } else if (CanvasView.getElements().get(listSize - 1) == 1) {

                  // I WANT TO CALL INVALIDATE() FROM HERE CanvasView.getPoints2().add(CanvasView.getPoints().get(CanvasView.getPoints().size() - 1));
                  CanvasView.getElements2().add(1);
                  CanvasView.getPoints().remove(CanvasView.getPoints().size() - 1);
                  CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              } else if (CanvasView.getElements().get(listSize - 1) == 2) {

                  CanvasView.getLines2().add(CanvasView.getLines().get(CanvasView.getLines().size() - 1));
                  CanvasView.getElements2().add(2);
                  CanvasView.getLines().remove(CanvasView.getLines().size() - 1);
                  CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              } else if (CanvasView.getElements().get(listSize - 1) == 3) {

                  CanvasView.getRectangles2().add(CanvasView.getRectangles2().get(CanvasView.getRectangles2().size() - 1));
                  CanvasView.getElements2().add(3);
                  CanvasView.getRectangles().remove(CanvasView.getRectangles().size() - 1);
                  CanvasView.getElements().remove(CanvasView.getElements().size() - 1);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              }
            return true;
        } else if (id == R.id.redo) {
            int listSize2 = CanvasView.getElements2().size();
              System.out.println(CanvasView.getElements2().size());
              if (CanvasView.getElements2().size() == 0) {
                return true;  
              } else if (CanvasView.getElements2().get(listSize2 - 1) == 1) {

                  CanvasView.getPoints().add(CanvasView.getPoints2().get(CanvasView.getPoints2().size() - 1));
                  CanvasView.getPoints2().remove(CanvasView.getPoints2().size() - 1);
                  CanvasView.getElements2().remove(CanvasView.getElements2().size() - 1);
                  CanvasView.getElements().add(1);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              } else if (CanvasView.getElements2().get(listSize2 - 1) == 2) {

                  CanvasView.getLines().add(CanvasView.getLines2().get(CanvasView.getLines2().size() - 1));
                  CanvasView.getLines2().remove(CanvasView.getLines2().size() - 1);
                  CanvasView.getElements2().remove(CanvasView.getElements().size() - 1);
                  CanvasView.getElements().add(2);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              } else if (CanvasView.getElements2().get(listSize2 - 1) == 3){

                  CanvasView.getRectangles().add(CanvasView.getRectangles2().get(CanvasView.getRectangles2().size() - 1));
                  CanvasView.getRectangles2().remove(CanvasView.getRectangles2().size() - 1);
                  CanvasView.getElements2().remove(CanvasView.getElements2().size() - 1);
                  CanvasView.getElements().add(3);
                  CanvasView.currentState = CanvasView.undoRedo.DoUndoRedo;
                  return true;
              }
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
      @Override
      public void onBackPressed() {
          AlertDialog.Builder builder = new AlertDialog.Builder(this);
          builder.setTitle("Exit");
          builder.setMessage("Are You Sure?");

          builder.setNegativeButton("Yes", new DialogInterface.OnClickListener() {
              public void onClick(DialogInterface dialog, int which) {
                      dialog.dismiss();
                      System.exit(0);
              }
          });   

          builder.setPositiveButton("No", new DialogInterface.OnClickListener() {
              @Override
              public void onClick(DialogInterface dialog, int which) {
                  dialog.dismiss();
              }
          });

          AlertDialog alert = builder.create();
          alert.show();

      }
}

Activiti_main.xml Activiti_main.xml

<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"
    android:id="@+id/rect"
    tools:context="com.example.HW3.MainActivity" >

    <com.example.HW3.CanvasView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

I am assuming you have defined your CanvasView in your res/layout/activity_main.xml (and assigned it an id, say "custom_view") You should not call your Canvas methods statically (directly from the class itself) but from the actual instance created by Android. 我假设您已经在res / layout / activity_main.xml中定义了CanvasView(并为其分配了一个ID,例如“ custom_view”),您不应静态地(直接从类本身)调用Canvas方法,而应从实际创建的实例中调用通过Android。 You can get it by changing your MainActivity to something like this: 您可以通过将MainActivity更改为以下内容来获得它:

public class MainActivity extends Activity {
private CanvasView canvasView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                            WindowManager.LayoutParams.FLAG_FULLSCREEN);

    setContentView(R.layout.activity_main);

    canvasView = findViewById(R.id.custom_view)
}

...

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    ...
    canvasView.invalidate();
    ...
}

You mention the error states that invalidate() isn't a static method. 您提到了错误状态,指出invalidate()不是静态方法。 Are you sure you're calling myCanvasInstance.invalidate() and NOT CanvasView.invalidate() ? 您确定要调用myCanvasInstance.invalidate()不是 CanvasView.invalidate()吗?

See these code below to make it clearer: 请参阅下面的这些代码,以使其更清晰:

protected void onCreate(Bundle savedInstanceState) {

    // This won't work.
    CanvasView.invalidate();

    // This will.
    CanvasView myView = new CanvasView();
    myView.invalidate();
} 

In fact, your code seem like treating all method calls as a static call. 实际上,您的代码似乎将所有方法调用都视为静态调用。 I don't know whether this is a typo or you are really doing it in your code. 我不知道这是拼写错误还是您在代码中确实在做。 The thing is, that's not the right way to do it - CanvasView is a class, not an instance/object. 事实是,这不是正确的方法CanvasView是一个类,而不是实例/对象。 You should interact with the instance, not with the class. 您应该与实例而不是与类进行交互。

For starters, change these line (and all those that are similar to it): 对于初学者,请更改以下行(以及所有与之相似的行):

CanvasView.getElements().size();
CanvasView.getElements2().add(1);
CanvasView.getLines().remove(CanvasView.getLines().size() - 1);
etc.

to something that looks like this: 看起来像这样:

// Define this on the top of your class (outside of any methods).
CanvasView myView;

// Do this on your onCreate() method.
myView = new CanvasView();

// ..and then code like these WILL work; even outside of onCreate().
myView.invalidate();
myView.getElements().size();
myView.getElements2().add(1);
myView.getLines().remove(CanvasView.getLines().size() - 1);
etc.

Hope this helped you. 希望这对您有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM