Swing GUI没有响应输入

时间:2017-02-13 22:03:09

标签: java swing

我正在筹建John Conway的生命游戏,以便在即将举行的会议上进行演示,我将该程序放在一个应该完成95%的地方,但是,没有任何回应用户输入。几乎看起来我的动作监听器和鼠标监听器没有正确实现,但我不知道在哪里。该计划几乎完全完成;有一些部分仍然是空的,但它仍然可以正确编译和创建我的JFrame。

/**
* 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 个答案:

答案 0 :(得分:1)

您的playGame功能在游戏结束前不会返回。 Swing UI是单线程的。在将控制权返回到swing运行时之前,它不会刷新。

您需要在后台任务中计算您的生活游戏,并通过触发框架中的绘画事件来重新绘制ui。

您可以在此处找到有关如何处理此问题的详细说明:Using threads to paint panel in java