2014-09-29 2 views
1

Программа должна запускать моделирование сотовых автоматов (думаю, жизнь жизни Конвея) на раскрашенной решетке и имеет кнопку запуска/паузы, чтобы запустить и приостановить симуляцию, которая запускается с интервалом в 1 секунду. Насколько я могу судить, все остальное, кроме рисования сетки (обработка, остальная часть графического интерфейса), отлично работает.Java Swing: проблема окраски сетки

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; 

      } 
     } 
    } 
} 

Он печатает что-то на самом верху, который выглядит как щепки исходной сетки накладываемой на полоске кнопку, а остальное серым по умолчанию.

+0

'catch (ArrayIndexOutOfBoundsException ae) {}' - никогда не делайте этого. Шутки в сторону. –

ответ

2

Ваша правая переменная добавлена ​​BorderLayout.NORTH не BorderLayout.CENTER, поэтому она заполняет только 5 верхних пикселей.

И как на мой комментарий, вы никогда не должны иметь код, как это в вашей программе:

catch(ArrayIndexOutOfBoundsException ae){} 

Не только вы должны не игнорировать исключения, но вы не должны даже поймать этот тип исключений. Вместо этого создайте свои петли с небольшой осторожностью, чтобы они могли обрабатывать края.

Кроме того, не забудьте вызвать метод super.paintComponent(g) в переопределении вашего класса.

Смежные вопросы