Java Jpanel重新绘制/更新问题
我对jpanel的重新绘制方法有问题。 我正试图使用Java Swing并遵循MVC架构制作一个“赛车游戏”: 我有5门课: 主:运行MVCJava 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
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;
}