Java Jpanel重新绘制/更新问题

Java Jpanel重新绘制/更新问题,java,swing,jpanel,repaint,Java,Swing,Jpanel,Repaint,我对jpanel的重新绘制方法有问题。 我正试图使用Java Swing并遵循MVC架构制作一个“赛车游戏”: 我有5门课: 主:运行MVC public class Main { private static Model model; private static View view; private static Controller controller; public static void main(String[] args) { m

我对jpanel的重新绘制方法有问题。 我正试图使用Java Swing并遵循MVC架构制作一个“赛车游戏”:

我有5门课: 主:运行MVC

public class Main {
    private static Model model;
    private static View view;
    private static Controller controller;

    public static void main(String[] args) {
        model = new Model();
        view =  new View();
        controller = new Controller();

        model.addObserver(view);

        controller.addModule(model);
        controller.addView(view);

        view.addContoller(controller);
    }
}
型号:

import java.util.ArrayList;
import java.util.Observable;


public class Model extends Observable{
    private ArrayList<Car> cars;// List of cars

    public Model() {
        cars = new ArrayList<Car>();
        cars.add(new Car(this,0, 50));
        cars.add(new Car(this,0, 50));
        cars.add(new Car(this,0, 50));
    }

    public void startCar(int i){
        //i is the index of the selected element in the checkbox
        //if i==0 then the selected element is "All cars" else is a specific car
        if(i>0)
            cars.get(i-1).start();
        else{
            for(int j=0;j<cars.size();j++)
                cars.get(j).start();
        }
    }

    public void speedUpCar(int i) {
        if(i>0)
            cars.get(i-1).incVitess();
        else{
            for(int j=0;j<cars.size();j++)
                cars.get(j).incVitess();
        }
    }

    public void notifyView(){
        setChanged();
        notifyObservers(cars);
    }

    public void speedDownCar(int i) {
        if(i>0)
            cars.get(i-1).decVitess();
        else{
            for(int j=0;j<cars.size();j++)
                cars.get(j).decVitess();
        }
    }

    public void stopCar(int i) {
        if(i>0)
            cars.get(i-1).stop();
        else{
            for(int j=0;j<cars.size();j++)
                cars.get(j).stop();
        }
    }
}
汽车等级:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;


public class Car extends JPanel{
    private int id,x,y,vitess;
    private Thread thread;
    private Model model;
    private boolean start = true;
    private boolean forward = true;
    private Color color;
    private boolean threadStarted = false;
    private BufferedImage bg; // background image

    public Car(Model model,int x,int y) {
        this.x =x;
        this.y = y;
        vitess = 7;
        this.model = model;

        try {
            bg = ImageIO.read(new File("road.png"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        color = changeColor(); // Random color

        thread = new Thread(new CarThread(this));

        start();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(bg, 0, 0, null); 
        g.setColor(color);
        g.fillRect(x, y, 100, 50); // the car is a simple rectangle
    }

    public void start() {
        start = true;
        if(!threadStarted){
            threadStarted = true;
            thread.start();
        }else{
            thread.resume();
        }
    }

    public void move(){
        System.out.println("X:"+x);
        if(forward){
            if(x<this.getWidth()){
                x+=2;
            }else{
                color = changeColor();
                forward = false;
            }
        }else{
            if(x>0){
                x-=2;
            }else{
                color = changeColor();
                forward = true;
            }
        }

        model.notifyView();
    }

    private Color changeColor() {
        int r = (int)(Math.random()*255);
        int g = (int)(Math.random()*255);
        int b = (int)(Math.random()*255);
        return new Color(r,g,b);
    }

    public void stop(){
        start = false;
        thread.suspend();
    }

    public void incVitess(){
        if(vitess>1)
            vitess--;
    }

    public void decVitess(){
        if(vitess<6)
            vitess++;
    }

    public int getId() {
        return id;
    }


    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getVitess() {
        return vitess;
    }   

    public boolean getStart(){
        return start;
    }

    public void setStart(boolean m){
        this.start = m;
    }

    public Color getColor(){
        return color;
    }
}
如果您运行该项目,您会注意到,即使使用以下方式,车辆也不会到达车架的末端:

if(x<this.getWidth()) x++;

if(x我不能说我已经阅读了您的所有代码,但是您的模型从未通知视图。我的意思是,模型类的代码中没有调用的
notifyView()
方法。只要状态发生更改,模型就应该负责调用该方法

请注意:

car.update(car.getGraphics()); // << the Problem is HERE
您无意中覆盖了Car JPanel的getX和getY方法,弄乱了这些组件的位置。这是避免在必要时覆盖Swing组件的另一个原因,以避免这些隐藏的副作用


删除或重命名这些方法。

在模型中,我有一个方法:
public void notifyView()
该方法由汽车的方法调用
public void Move()
,这意味着每当线程调用car的move方法时,它都会调用model@EssaidiM有一个问题,您正在修改视图,它更新了模式,通知了视图??线程应该通知模型,模型更新了视图。视图将更新自身,以表示模型…和Swing不是线程安全的…@EssaidiM同样,您的控制器应该是视图和模型之间的通信连接点,视图和模型不应该直接通信(如果您想要纯MVC)@EssaidiM:虽然我知道有MVC的变体,模型会通知视图,如果遵循它,这是合法的,但是你的没有这样做。好的,我会尝试更正我的MVC,并检查重新绘制方法是否符合我的预期。我可以用什么替换挂起和恢复?
public class CarThread implements Runnable{
    private Car car;

    public CarThread(Car car) {
        this.car = car;
    }

    @Override
    public void run() {
        while(car.getStart()){
            car.move();
            try {
                Thread.sleep(car.getVitess());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}
if(x<this.getWidth()) x++;
car.repaint(); // << the Problem is HERE
car.update(car.getGraphics()); // << the Problem is HERE
car.update(car.getGraphics()); // << the Problem is HERE
class Car extends JPanel {
    private int id, x, y, vitess;

    //....

    public int getX() {
       return x;
    }

    public int getY() {
       return y;
    }