简体   繁体   中英

Repaint only working when I click the button

Hi I have implemented a MVC for a simulation and am using JPanel to draw each simulation cycle when I iterate through a collection of agents and update their position in the 2D array. However the repaint method isnt working correctly for me the JPanel should automatically keep refreshing when I click the start button once. But if I keep clicking on the start button then is repaints the JPanel with the updated positions of the agents what am i doing wrong ??

GUI Class:
    public class MainGUI implements Runnable {

        public static void main(String[] args) {
            EventQueue.invokeLater(new MainGUI());
        }

        @Override
        public void run() {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new MainPanel());
            f.pack();
            f.setLocationRelativeTo(null);
            f.setSize(400, 400);
            f.setVisible(true);
            f.repaint();
        }

        class MainPanel extends JPanel {

            public MainPanel() {
                super(new BorderLayout());

                Simulator model = new Simulator();
                GridView view1 = new GridView(model);
                Controller control = new Controller(model, view1);
                JLabel label = new JLabel("Welcome to the ABM Simulation");


                this.add(label, BorderLayout.NORTH);
                this.add(view1, BorderLayout.CENTER);
                this.add(control, BorderLayout.SOUTH);
            }
        }


    }

    View Class:

        public class GridView extends JPanel {

            private Simulator sim;
            private int rows;
            private int cols;
            private Agent[][] current2DArray;

            public GridView(Simulator sim) {
                this.sim = sim;
                this.rows = sim.getGrid().getRow();
                this.cols = sim.getGrid().getColumn();
                this.current2DArray = sim.getGrid().getGrid();

                JPanel canvas = new JPanel();
                canvas.setLayout(null);
                canvas.setPreferredSize(new Dimension(rows, cols));
            }

            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                setBackground(Color.GRAY);

                for(Agent agent : sim.getAgents()) {
                    g.setColor(agent.getColor());
                    g.fill3DRect(agent.getLocation().getRow(), agent.getLocation().getCol(), 5, 5, true);
               repaint();
                }
            }

        public void drawAgents(Graphics g) {
            g.setColor(Color.GRAY);
            g.fillRect(0,0,rows,cols);
            for(int row = 0; row < current2DArray.length; row++) {
                for(int col = 0; col < current2DArray[row].length; col++) {
                    if(current2DArray[row][col] instanceof Cop) {
                        if(current2DArray[row][col].getState() == 1) {
                            g.setColor(Color.RED); 
                            g.fill3DRect(row, col, 5, 5, true);
                        }
                        else if(current2DArray[row][col].getState() == 2) {
                            //no nothing
                        }

                    }
                    else if(current2DArray[row][col] instanceof Citizen) {
                        if(current2DArray[row][col].getState() == 3) {
                            g.setColor(Color.BLACK);
                            g.fill3DRect(row, col, 5, 5, true);
                        }
                        else if(current2DArray[row][col].getState() == 4) {
                            //no nothing
                        }
                    }
                    else if(current2DArray[row][col] == null) {
                        //if empty do nothing
                    }
                }
            }
        }
    }

public class Controller extends JPanel {
    private Simulator sim;
    private GridView view;
    private JButton start = new JButton("Start");

    public Controller(Simulator sim, GridView view) {
        this.sim = sim;
        this.view = view;
        this.add(start);
        start.addActionListener(new ButtonHandler());
    }

    private class ButtonHandler implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            String cmd = e.getActionCommand(); {
                if("Start".equals(cmd)) {
                    sim.resumeSimulation();
                }
            }
        }

    }
}

Call repaint() on your JPanel after each simulation cycle to get it re-painted. Pressing the button inadvertently triggers this.

So create a reference to your panel somewhere that the simulation can access, then invoke the repaint() method ie myGridView.repaint() .

If you want a constant frame rate then you can set a Timer to force your panel to repaint.

Swing object usually do as little as they can unless told otherwise by their components or by you and expecting cooperation from then leads to heartache.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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