繁体   English   中英

Java Swing:绘制网格问题

[英]Java Swing: Issue painting a grid

该程序应该在绘制的网格上运行元胞自动机模拟(想想康威的人生游戏),并具有一个开始/暂停按钮以开始/暂停模拟,该间隔每1秒运行一次。 据我所知,除绘制网格(处理,GUI的其余部分)外,其他所有东西都可以正常工作。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ConcurrentModificationException;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;


public class CA_DriverV2 extends JFrame{

    private static final Color white = Color.WHITE, black = Color.BLACK;

    private Board board;
    private JButton start_pause;

    public CA_DriverV2(){

        board = new Board();
        board.setBackground(white);

        start_pause = new JButton("Start");
        start_pause.addActionListener(board);

        this.add(board, BorderLayout.NORTH);
        this.add(start_pause, BorderLayout.SOUTH);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setSize(300, 300);
        this.setVisible(true);

    }

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

    private class Board extends JPanel implements ActionListener{

        private final Dimension DEFAULT_SIZE = new Dimension(5, 5);
        private final int DEFAULT_CELL = 10, DEFAULT_INTERVAL = 1000, DEFAULT_RATIO = 60;

        private Dimension board_size;
        private int cell_size, interval, fill_ratio;
        private boolean run;
        private Timer timer;

        private Color[][] grid;

        public Board(){
            board_size = DEFAULT_SIZE;
            cell_size = DEFAULT_CELL;
            interval = DEFAULT_INTERVAL;
            fill_ratio = DEFAULT_RATIO;
            run = false;

            //Initialize grid with random values
                //NOTE: Add JOptionPane for option to define fill rate and board size?
                //ALT: Have a resize(int h, int w) method to resize grid when needed.
                //ALT: Have refill(int r) method to restart with different fill ratio.
            grid = new Color[board_size.height][board_size.width];
            for (int h = 0; h < board_size.height; h++)
                for (int w = 0; w < board_size.width; w++){
                    int r = (int)(Math.random() * 100);
                    if (r >= fill_ratio)
                        grid[h][w] = black;
                    else grid[h][w] = white;
                }

            timer = new Timer(interval, this);
        }

        @Override
        public Dimension getPreferredSize(){
            return new Dimension(board_size.height, board_size.width);
        }

        @Override
        public void paintComponent(Graphics g){
            for (int h = 0; h < board_size.height; h++)
                for (int w = 0; w < board_size.width; w++){
                    try{
                        if (grid[h][w] == black)
                            g.setColor(black);
                        else g.setColor(white);
                        g.fillRect(h * cell_size, w * cell_size, cell_size, cell_size);
                    } catch (ConcurrentModificationException cme){}
                }
        }

        public void actionPerformed(ActionEvent e) {

            //Timer tick processing
            if (e.getSource().equals(timer)){
                repaint();
                Color[][] newGrid = new Color[board_size.height][board_size.width];
                for (int h = 1; h < board_size.height; h++)
                    for (int w = 1; w < board_size.height; w++) {
                        int surrounding = 0;
                        //Count black neighbors
                        for (int i = -1; i <= 1; i++)
                            for (int j = -1; j <= 1; j++){
                                if(i != 0 && j != 0){
                                    try{
                                        if(grid[h + i][w + j] == black)
                                            surrounding++;
                                    } catch(ArrayIndexOutOfBoundsException ae){}
                                }
                            }



                        //Generate next iteration
                        if (surrounding > 5 || surrounding < 2)
                            newGrid[h][w] = black;
                        else newGrid[h][w] = white;
                    }
                for (int h = 1; h < board_size.height; h++){
                    for (int w = 1; w < board_size.height; w++){
                        grid[h][w] = newGrid[h][w];
                        System.out.print(grid[h][w] + " ");
                    }
                    System.out.println();
                }
                System.out.println();
            }

            //Start-Pause button processing
            else if(e.getSource().equals(start_pause)){
                if(run){
                    timer.stop();
                    start_pause.setText("Pause");
                }
                else {
                    timer.restart();
                    start_pause.setText("Start");
                }
                run = !run;

            }
        }
    }
}

它在最顶部打印出一些内容,看起来像是初始网格的一小部分被按钮的一小部分覆盖,其余部分是默认的灰色。

您的面板Board变量被添加为BorderLayout.NORTH而不是BorderLayout.CENTER,因此它仅填充前5个像素。

根据我的评论,程序中永远不要包含这样的代码:

catch(ArrayIndexOutOfBoundsException ae){}

您不仅不应该忽略异常,而且甚至不应该捕获这种类型的异常。 而是稍微小心地创建for循环,以便它们可以处理边缘。

另外,不要忘记在类的重写中调用super.paintComponent(g)方法。

暂无
暂无

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

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