摆动和多线程:汽车为什么会碰撞?

时间:2019-01-29 10:53:21

标签: java multithreading swing custom-painting

这是我为带有图形用户界面的十字路并发应用程序所做的实现,但是在运行应用程序一段时间后出现了某种冲突,无法真正解决实际问题 请原谅我的减价幅度很差,谢谢您的支持

我的窗口类:

package com.example.trafic;

import javax.swing.*;

public class Window extends JFrame {
    View view = new View();

    public Window(){
        this.setTitle("Trafic App");
        this.setSize(720, 450);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setContentPane(view);
        this.setResizable(false);
        this.setVisible(true);
    }
}

我的View类:

package com.example.trafic;

import javax.swing.*;
import java.awt.*;

public class View extends JPanel {
    //private Thread t;

    // DIMENSION
    public int width = 720;
    public int height = 420;
    public int route_width = 100;
    public int lamp_width = 30;
    public int car_width = 60;
    public int car_height = 70;

    public int positionV = 0;
    public int positionH = 0;
    public int feu = 1;

    @Override
    public void paintComponent(Graphics g2) {
        // TEXTTURE
        g2.setColor(Color.DARK_GRAY);
        g2.fillRect(0, 0, width, height);

        // ROUTE
        g2.setColor(Color.LIGHT_GRAY);
        g2.fillRect( width / 2 - route_width / 2, 0, route_width, 420);
        g2.fillRect(0, height / 2 - route_width / 2, 720, route_width);

        // LAMPE
        g2.setColor((feu == 1 ) ? Color.RED : Color.GREEN );
        g2.fillOval(width / 2 - route_width, height / 2 - route_width, lamp_width, lamp_width);
        g2.setColor((feu == 2 ) ? Color.RED : Color.GREEN);
        g2.fillOval(width / 2 + route_width - 30, height / 2 - route_width , lamp_width, lamp_width);
        ImageIcon ia = new ImageIcon(View.class.getResource("/images/carh.png"));
        Image carH = ia.getImage();
        ImageIcon ib = new ImageIcon(View.class.getResource("/images/carv.png"));
        Image carV = ib.getImage();
        g2.drawImage(carH, 10 + width / 2 - car_width / 2, 10 + positionH, this);
        g2.drawImage(carV, 720 - positionV, 10 + height / 2 - car_height / 2, this);
    }

    public void setLight(int feu){
        this.feu = feu;
        this.repaint();
    }

    public void setCarV(int i){
        this.positionV = i;
        this.repaint();
    }

    public void setCarH(int i) {
        this.positionH = i;
        this.repaint();
    }
}

我的任务班:

package com.example.trafic;

public class Task implements Runnable {
    Window frame;
    static int Feu = 1;

    public Task(Window frame) {
        this.frame = frame;
    }

    public void run() {
        while (true) {
            try {
                Thread.sleep(4000);
                if (Feu == 1) {
                    Feu = 2;
                    System.out.println("Feu 2 ON");
                } else {
                    Feu = 1;
                    System.out.println("Feu 1 ON");
                }
                frame.view.setLight(Feu);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

我的跑步课:

package com.example.trafic;

public class Run implements Runnable {
    View view;

    public Run(View view) {
        this.view = view;
    }

    public void run() {
        while (Task.Feu == 2) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        while(true){
            int i = 0 ;

            int l = (Task.Feu == 1) ? 720 : 450;
            for (int j = 0; j < l; j++) {
                try {
                    Thread.sleep(2);
                    if ((Task.Feu == 1)) {
                        view.setCarV(++i);
                    } else {
                        view.setCarH(++i);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

我的应用主班:

package com.example.trafic;

public class App {
    public static void main(String[] args) throws InterruptedException {
        Window frame = new Window();
        new Thread(new Task(frame)).start();
        new Thread(new Run(frame.view)).start();
    }
}

1 个答案:

答案 0 :(得分:1)

以下代码实现了Model-View-Controller模式,以演示一个简单的结点控制,该问题已尝试进行。
该代码是一个文件的MCVE:可以将其复制粘贴到Junction.java中并运行。
请注意以下注释:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

//serves as controller. "wires" up model, view and updating thread
public class Junction {

    private static final int TRAFFIC_LIGHT_CYCLE = 4000;
    private boolean isVerticalRed = false;

    Junction() {
        Model model = new Model();
        Window frame = new Window(model);
        model.setObserver(frame);
        //use time to change lights
        Timer timer = new Timer(TRAFFIC_LIGHT_CYCLE, e->{
            isVerticalRed = ! isVerticalRed;
            model.setVerticalRed(isVerticalRed);
        });

        timer.start();
        new Thread(new CarsUpdater(model)).start();
    }

    public static void main(String[] args) {
        new Junction();
    }
}

//view of the mvc model. listens to changes in model using Observer interface
class Window extends JFrame implements Observer{

    private final View view;

    public Window(Model model){

        this.setTitle("Trafic App");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        view = new View(model);
        this.setContentPane(view);
        pack();
        this.setResizable(false);
        this.setVisible(true);
    }

    //respond to model changes
    @Override
    public void changed() {
        repaint();
    }
}

class View extends JPanel {

    // DIMENSION
    private final static int ROUTE_WIDTH = 100, LAMP_WIDTH = 30;
    private final int CAR_WIDTH = 60, CAR_HEIGHT = 70;

    //Construct resources once
    private Image carH, carV;

    private final Model model;

    View(Model model) {

        this.model = model;

        //Construct resources once
        try {
            //use publically available resources to make code mcve 
            ImageIcon ia = new ImageIcon(new URL("https://i.imgur.com/wIO1liB.png"));
            carH = ia.getImage();
            ImageIcon ib = new ImageIcon(new URL("https://i.imgur.com/gEbZMHe.png"));
            carV = ib.getImage();
        } catch (MalformedURLException ex) {
            ex.printStackTrace();
        }

        setPreferredSize(new Dimension(model.getWidth(), model.getHeight()));
    }

    @Override
    public void paintComponent(Graphics g2) {

        super.paintComponent(g2);
        // TEXTTURE
        g2.setColor(Color.DARK_GRAY);
        g2.fillRect(0, 0, model.getWidth(), model.getHeight());

        // ROUTE
        g2.setColor(Color.LIGHT_GRAY);
        g2.fillRect( model.getWidth() / 2 - ROUTE_WIDTH / 2, 0, ROUTE_WIDTH, 420);
        g2.fillRect(0, model.getHeight() / 2 - ROUTE_WIDTH / 2,  model.getWidth(), ROUTE_WIDTH);

        // LAMPE
        g2.setColor(model.isVerticalRed() ?  Color.RED : Color.GREEN  );
        g2.fillOval(model.getWidth() / 2 - ROUTE_WIDTH,  model.getHeight() / 2 - ROUTE_WIDTH, LAMP_WIDTH, LAMP_WIDTH);

        g2.setColor(model.isVerticalRed() ? Color.GREEN : Color.RED);
        g2.fillOval( model.getWidth() / 2 + ROUTE_WIDTH - 30,  model.getHeight()/ 2 - ROUTE_WIDTH , LAMP_WIDTH, LAMP_WIDTH);

        g2.drawImage(carH, 10 + model.getWidth() / 2 - CAR_WIDTH / 2, 10 + model.getVerticalCarPosition(), this);
        g2.drawImage(carV,  model.getWidth() - model.getHorizontalCarPosition(), 10 +  model.getHeight() / 2 - CAR_HEIGHT / 2, this);
    }
}

interface Observer {
    void changed();
}

//model encapsulates information that view needs
class Model {

    private final static int W = 720, H = 420;
    private static final long SPEED = 2;
    private Observer observer;

    //is read / write by more than one thread getters and setters
    //need to be synchronized
    private boolean isVerticalRed = false;     //boolean to flag which light is red
    private int hPosition = 0,  vPosition = 0;

    boolean isVerticalRed() {
        return isVerticalRed;
    }

    void setVerticalRed(boolean isVerticalRed) {
        this.isVerticalRed = isVerticalRed;
        notifyObserver();
    }

    int getHorizontalCarPosition(){
        return hPosition;
    }

    //move horizontal car continuously, until meets stop condition
    void clearHorizontalCarFromJunction() throws InterruptedException{
        while(hPosition != W / 3){
            Thread.sleep(SPEED);
            stepHorizontal();
        }
    }

    //move horizontal one step
    void stepHorizontal(){
        int newH= hPosition  +1 > W ?  0 : hPosition +1;
        setHorizontalCarPosition(newH);
    }

    void setHorizontalCarPosition(int i){
        hPosition = i;
        notifyObserver();
    }

    //move vertical car continuously, until meets stop condition
    void clearVerticalCarFromJunction() throws InterruptedException{
        while(vPosition != H / 4){
            Thread.sleep(SPEED);
            stepVertical();
        }
    }
    //move vertical car one step
    void stepVertical(){
        int newV = vPosition +1 > H ?  0 : vPosition +1;
        setVerticalCarPosition(newV);
    }

    int getVerticalCarPosition(){
        return vPosition;
    }

    void setVerticalCarPosition(int i) {
        vPosition = i;
        notifyObserver();
    }

    int getWidth(){ return W;   }

    int getHeight(){ return H;  }

    void setObserver(Observer observer) {
        this.observer = observer;
    }

    void notifyObserver(){
        if(observer != null) {
            observer.changed();
        }
    }

    long getSpeed(){
        return SPEED;
    }
}

class CarsUpdater implements Runnable {

    private final Model model;

    public CarsUpdater(Model model) {
        this.model = model;
    }

    @Override
    public void run() {

        while(true){;

            try {

                Thread.sleep(model.getSpeed());
                if (model.isVerticalRed()) {
                    model.clearVerticalCarFromJunction();
                    model.stepHorizontal();
                } else {
                    model.clearHorizontalCarFromJunction();
                    model.stepVertical();
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

enter image description here