2017-02-13 34 views
0

我正在爲即將舉行的會議上的演示建模John Conway的Game of Life進行工作,並且我在一個應該完成95%的地方開發該程序,但是,沒有任何響應用戶輸入。它幾乎看起來像我的動作監聽器和鼠標監聽器沒有正確實現,但我不知道在哪裏。該計劃幾乎完全完成;有幾個部分仍然是空的,但它仍然會編譯並正確創建我的JFrame。Swing GUI未對輸入做出響應

/** 
* Created by Brendan Kristiansen on 1/26/2017. 
*/ 
public class GameOfLife 
{ 
    public static void main(String[] args) 
    { 
     MyFrame frame = new MyFrame(); 
    } 
} 

類,它包含全局信息:

/** 
* Created by Brendan Kristiansen on 1/26/2017. 
*/ 
public class GLOBAL 
{ 
    /** 
    * Build Information for GameOfLife 
    */ 
    public static final double BUILDVERSION = 0.1; 
    public static final String BUILDNAME = "Alpha 0.1"; 

    /** 
    * Global Constants for GameOfLife 
    */ 
    public static final int FRAMEHEIGHT = 1000;  //Frame Height 
    public static final int FRAMEWIDTH = 1000;  //Frame Width 
    public static final int HEIGHT = 100;   //Game Height 
    public static final int WIDTH = 100;   //Game Width 

    /** 
    * Global Variables 
    */ 
    public static int delay = 500;     //Step Delay (Milliseconds) 
    public static byte[][] herd0;     //Herd Byte Array 0 
    public static byte[][] herd1;     //Herd Byte Array 2 
    public static byte[][] startHerd;    //Customized herd before animation is started 
    public static byte activeArray;     //Array currently being displayed 
    public static boolean active;     //States if simulation is repeating 
    public static long arraySwitches;    //Tallies times active array is switched 

    /** 
    * Action Commands 
    */ 
    public static final String CLOSE = "close";   //Closes Application 
    public static final String START = "go";   //Starts looping simulation 
    public static final String STOP = "stop";   //Stops loop 
    public static final String RULES = "rules";   //Pops up window with Rules for GOL 
    public static final String ABOUT = "about";   //Displays about dialog 
    public static final String RESETGRID = "resetGrid"; //Resets the grid to before the simulation 
    public static final String NEWGAME = "new";   //Zeroes the grid and arrays 
} 

框架:

/** 
* Created by Brendan Kristiansen on 1/26/2017. 
*/ 

import java.awt.*; 
import java.awt.event.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 
import javax.swing.event.*; 

/** 
* @author Brendan Kristiansen 
*/ 
public class MyFrame extends JFrame implements ActionListener, ChangeListener 
{ 
    private JPanel mPanel; 
    private JButton start; 
    private JButton stop; 
    private JButton setGame; 
    private JButton resetGame; 
    private JButton newGame; 

    private JLabel speedLabel; 
    private JSlider speed; 

    private HerdPanel mHerdPanel; 

    /** 
    * Constructor 
    */ 
    public MyFrame() 
    { 
     GLOBAL.active = false; 
     initArrays(); 
     setSize(GLOBAL.FRAMEWIDTH, GLOBAL.FRAMEHEIGHT); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     mPanel = new JPanel(); 
     initForm(); 
     setVisible(true); 
     mPanel.setVisible(true); 

     JMenuBar menu = new JMenuBar(); 

     JMenu game = new JMenu("GameOfLife"); 
     JMenu help = new JMenu("Help"); 

     JMenuItem gamePlay = new JMenuItem("Play"); 
     JMenuItem gameExit = new JMenuItem("Exit"); 
     JMenuItem helpRules = new JMenuItem("Rules"); 
     JMenuItem helpAbout = new JMenuItem("About"); 

     gamePlay.addActionListener(this); 
     gameExit.addActionListener(this); 
     helpRules.addActionListener(this); 
     helpAbout.addActionListener(this); 

     gamePlay.setActionCommand(GLOBAL.START); 
     gameExit.setActionCommand(GLOBAL.CLOSE); 
     helpRules.setActionCommand(GLOBAL.RULES); 
     helpAbout.setActionCommand(GLOBAL.ABOUT); 

     game.add(gamePlay); 
     game.add(gameExit); 
     help.add(helpRules); 
     help.add(helpAbout); 

     menu.add(game); 
     menu.add(help); 

     this.setJMenuBar(menu); 
     this.setVisible(true); 
    } 

    /** 
    * Lays Out Panel 
    */ 
    public void initForm() 
    { 
     setGame = new JButton("Set Grid"); 
     resetGame = new JButton("Reset Grid"); 
     newGame = new JButton("Clear Grid"); 
     start = new JButton("Start Simulation"); 
     stop = new JButton("Stop Simulation"); 
     speedLabel = new JLabel("Simulation Speed (ms): " + GLOBAL.delay); 
// N  speed = new JSlider(3000, 50, GLOBAL.delay); 

     setGame.addActionListener(this); 
     resetGame.addActionListener(this); 
     newGame.addActionListener(this); 
     start.addActionListener(this); 
     stop.addActionListener(this); 

//  setGame.setActionCommand(GLOBAL.SETGRID); 
     resetGame.setActionCommand(GLOBAL.RESETGRID); 
     newGame.setActionCommand(GLOBAL.NEWGAME); 
     start.setActionCommand(GLOBAL.START); 
     stop.setActionCommand(GLOBAL.STOP); 

     mPanel = new JPanel(); 
     mPanel.setLayout(new BoxLayout(mPanel, BoxLayout.X_AXIS)); 
     mPanel.setBackground(new Color(100, 100, 100)); 

     mHerdPanel = new HerdPanel(); 

     mPanel.add(setGame); 
     mPanel.add(resetGame); 
     mPanel.add(newGame); 
     mPanel.add(start); 
     mPanel.add(stop); 
//  mPanel.add(speedLabel); 
//  mPanel.add(speed); 

     getContentPane().add(mPanel, BorderLayout.NORTH); 
     getContentPane().add(mHerdPanel, BorderLayout.CENTER); 

    } 

    /** 
    * Directs ActionEvents to the proper functions 
    * @param event 
    */ 
    @Override 
    public void actionPerformed(ActionEvent event) 
    { 
     String e = event.toString(); 
     if(e.equals(GLOBAL.CLOSE)) 
     { 
      System.exit(0); 
     } 
     else if(e.equals(GLOBAL.START)) 
     { 
      GLOBAL.active = true; 
      playGame(); 
     } 
     else if(e.equals(GLOBAL.STOP)) 
     { 
      GLOBAL.active = false; 
     } 
     else if(e.equals(GLOBAL.NEWGAME)) 
     { 
      initArrays(); 
      mHerdPanel.paintImage(); 
     } 
     else if(e.equals(GLOBAL.RESETGRID)) 
     { 
      GLOBAL.herd0 = GLOBAL.startHerd; 
      GLOBAL.herd1 = GLOBAL.startHerd; 
      GLOBAL.activeArray = 0; 
      mHerdPanel.paintImage(); 
     } 
     else if (e.equals(GLOBAL.ABOUT)) 
     { 
      JOptionPane.showMessageDialog(null, "Game of Life\n Developed by Brendan Kristiansen with MSU Storytelling."); 
     } 
     else if (e.equals(GLOBAL.RULES)) 
     { 

     } 
    } 

    /** 
    * Directs ChangeEvents to the proper functions 
    * @param e 
    */ 
    @Override 
    public void stateChanged(ChangeEvent e) 
    { 
     GLOBAL.delay = speed.getValue(); 
    } 

    /** 
    * initializes byte arrays to be 0 
    */ 
    public void initArrays() 
    { 
     GLOBAL.herd0 = new byte[GLOBAL.HEIGHT][GLOBAL.WIDTH]; 
     GLOBAL.herd1 = new byte[GLOBAL.HEIGHT][GLOBAL.WIDTH]; 
     for(int i = 0; i <= GLOBAL.HEIGHT - 1; i++) 
     { 
      for(int j = 0; j <= GLOBAL.WIDTH - 1; j++) 
      { 
       GLOBAL.herd0[i][j] = 0; 
      } 
     } 
     GLOBAL.herd1 = GLOBAL.herd0; 
     GLOBAL.activeArray = 0; 
     GLOBAL.arraySwitches = 0; 
    } 

    /** 
    *Controls the advancement of the game 
    */ 
    public void playGame() 
    { 
     GLOBAL.startHerd = GLOBAL.herd0; 
     if (GLOBAL.active == true) 
     { 
      while(GLOBAL.active == true) 
      { 
       nextFrame(); 
       try 
       { 
        wait(GLOBAL.delay); 
       } 
       catch(Exception e) 
       { 
        System.out.println(e); 
       } 
      } 
     } 
     else 
     { 
      nextFrame(); 
     } 
    } 

    /** 
    *Advances Game of Life by one frame 
    */ 
    public void nextFrame() 
    { 
     if (GLOBAL.activeArray == 0) 
     { 
      for(int i = 0; i <= GLOBAL.HEIGHT; i++) 
      { 
       for(int j = 0; j <= GLOBAL.WIDTH; j++) 
       { 
        int neighbors = countNeighbors(i, j, GLOBAL.herd0); 
        if (neighbors == 3 || neighbors == 4) 
        { 
         GLOBAL.herd1[i][j] = 1; 
        } 
        else 
        { 
         GLOBAL.herd1[i][j] = 0; 
        } 
       } 
      } 
      GLOBAL.activeArray = 1; 
      mHerdPanel.paintImage(); 
     } 
     else 
     { 
      for(int i = 0; i <= GLOBAL.HEIGHT; i++) 
      { 
       for(int j = 0; j <= GLOBAL.WIDTH; j++) 
       { 
        int neighbors = countNeighbors(i, j, GLOBAL.herd1); 
        if (neighbors == 3 || neighbors == 4) 
        { 
         GLOBAL.herd0[i][j] = 1; 
        } 
        else 
        { 
         GLOBAL.herd0[i][j] = 0; 
        } 
       } 
      } 
      GLOBAL.activeArray = 0; 
      mHerdPanel.paintImage(); 
     } 
     GLOBAL.arraySwitches++; 
    } 

    /** 
    * Counts the living neighbors of a given cell in a herd 
    * @param i 
    * @param j 
    * @param herd 
    * @return 
    */ 
    public int countNeighbors(int i, int j, byte[][] herd) 
    { 
     int neighbors = 0; 
     if(i == 0 && j == 0) //Top left case 
     { 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom Neighbor 
      if(herd[i + 1][j + 1] == 1){neighbors++;} //Bottom right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
     } 
     else if(i == 0 && j == GLOBAL.WIDTH) //Top right case 
     { 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom neighbor 
      if(herd[i + 1][j - 1] == 1){neighbors++;} //Bottom left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
     } 
     else if(i == GLOBAL.HEIGHT && j == 0) //Bottom left case 
     { 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i - 1][j + 1] == 1){neighbors++;} //Top right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
     } 
     else if(i == GLOBAL.HEIGHT && j == GLOBAL.WIDTH) //Bottom right case 
     { 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i - 1][j - 1] == 1){neighbors++;} //Top left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
     } 
     else if(i == 0) //Top Row 
     { 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom neighbor 
      if(herd[i + 1][j + 1] == 1){neighbors++;} //Bottom right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
      if(herd[i + 1][j - 1] == 1){neighbors++;} //Bottom left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
     } 
     else if(j == 0) //Left side 
     { 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom neighbor 
      if(herd[i + 1][j + 1] == 1){neighbors++;} //Bottom right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i - 1][j + 1] == 1){neighbors++;} //Top right neighbor 
     } 
     else if(i == GLOBAL.HEIGHT) //Bottom Row 
     { 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i - 1][j + 1] == 1){neighbors++;} //Top right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
      if(herd[i - 1][j - 1] == 1){neighbors++;} //Top left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
     } 
     else if(j == GLOBAL.WIDTH) //Right side 
     { 
      if(herd[i - 1][j - 1] == 1){neighbors++;} //Top left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom neighbor 
      if(herd[i + 1][j - 1] == 1){neighbors++;} //Bottom left neighbor 
     } 
     else //Middle of herd 
     { 
      if(herd[i + 1][j] == 1){neighbors++;}  //Bottom neighbor 
      if(herd[i + 1][j - 1] == 1){neighbors++;} //Bottom left neighbor 
      if(herd[i][j - 1] == 1){neighbors++;}  //Left neighbor 
      if(herd[i - 1][j - 1] == 1){neighbors++;} //Top left neighbor 
      if(herd[i - 1][j] == 1){neighbors++;}  //Top neighbor 
      if(herd[i - 1][j + 1] == 1){neighbors++;} //Top right neighbor 
      if(herd[i][j + 1] == 1){neighbors++;}  //Right neighbor 
      if(herd[i + 1][j + 1] == 1){neighbors++;} //Bottom right neighbor 
     } 
     return neighbors; 
    } 
} 

而且HerdPanel類。這應該是一個網格,您可以點擊更改單元格的顏色,然後玩遊戲生活已經突出顯示的細胞:

/** 
* 
* @author Brendan Kristiansen 
*/ 
import javax.imageio.ImageIO; 
import java.io.File; 
import java.io.IOException; 
import javax.swing.*; 
import java.awt.event.*; 
import java.awt.*; 
import java.awt.image.BufferedImage; 

//https://www.shodor.org/stella2java/rgbint.htmlhttps://www.shodor.org/stella2java/rgbint.html 

public class HerdPanel extends JPanel implements MouseListener, MouseMotionListener 
{ 
    Graphics2D g; 
    Graphics2D g2; 
    BufferedImage grid; 
    BufferedImage bisonCell; 

    /** 
    * Constructor 
    */ 
    public HerdPanel() 
    { 
     setSize(500, 500); //Width, Height 
     addMouseListener(this); 
     addMouseMotionListener(this); 
     try 
     { 
      bisonCell = ImageIO.read(new File("bison.png")); 
     } 
     catch (IOException e) 
     { 
      System.out.println(e); 
     } 
     grid = new BufferedImage(GLOBAL.WIDTH, GLOBAL.HEIGHT, 1); 
     paintImage(); 
     //g = grid.createGraphics(); 
    } 

    /** 
    * Converts byte[][] array to BufferedImage 
    */ 
    public void paintImage() 
    { 
     if (GLOBAL.activeArray == 0) 
     { 
      for (int i = 0; i <= GLOBAL.WIDTH - 1; i++) 
      { 
       for (int j = 0; j <= GLOBAL.HEIGHT - 1; j++) 
       { 
        if (GLOBAL.herd0[j][i] == 0) 
        { 
         grid.setRGB(j, i, 16777215); 
        } else 
        { 
         grid.setRGB(j, i, 0); 
        } 
       } 
      } 
     } 
     else 
     { 
      for (int i = 0; i <= GLOBAL.WIDTH; i++) 
      { 
       for (int j = 0; j <= GLOBAL.HEIGHT; j++) 
       { 
        if (GLOBAL.herd1[j][i] == 0) 
        { 
         grid.setRGB(j, i, 16777215); 
        } else 
        { 
         grid.setRGB(j, i, 0); 
        } 
       } 
      } 
     } 
     g = grid.createGraphics(); 
     super.paintComponent(g); 
     g.drawImage(grid, null, 0, 0); 
     repaint(); 
    } 

    @Override 
    public void mouseClicked(MouseEvent e) 
    { 
     int xClick = (int)(e.getX()/GLOBAL.WIDTH); 
     int yClick = (int) (e.getY()/GLOBAL.HEIGHT); 
     if(GLOBAL.activeArray == 0) 
     { 
      GLOBAL.herd0[yClick][xClick] = 1; 
     } 
     else 
     { 
      GLOBAL.herd1[yClick][xClick] = 1; 
     } 
     paintImage(); 
    } 

    @Override 
    public void mousePressed(MouseEvent e) 
    { 
    } 

    @Override 
    public void mouseReleased(MouseEvent e) 
    { 
    } 

    @Override 
    public void mouseEntered(MouseEvent e) 
    { 
    } 

    @Override 
    public void mouseExited(MouseEvent e) 
    { 
    } 

    @Override 
    public void mouseDragged(MouseEvent e) 
    { 
    } 


    @Override 
    public void mouseMoved(MouseEvent e) 
    { 
    } 
} 
+1

您阻止事件指派線程,阻止它畫,看看[併發在Swing(https://開頭的文檔.oracle.com/javase/tutorial/uiswing/concurrency /)以獲得更多詳細信息以及[如何使用Swing Timers](https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)簡單的解決方案 – MadProgrammer

+0

對於需要定期更新UI的更復雜或更耗時的任務,應該使用['SwingWorker'](https://docs.oracle.com/javase/tutorial/uiswing/concurrency /worker.html) – MadProgrammer

回答

1

playGame功能不會返回,直到比賽結束。 Swing UI是單線程的。直到您將控制權返回給擺動運行時,它纔會刷新。

您需要在後臺任務中計算您的生活遊戲,並通過在框架中觸發繪畫事件來重新繪製UI。

你可以找到關於如何在這裏處理這一個很好的解釋:Using threads to paint panel in java