-1

另一个问题,相同的程序:

下面是MainGUI.java

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class MainGUI extends JFrame implements ActionListener
{

    private static final long   serialVersionUID    = 4149825008429377286L;

    private final double version = 8;

    public static int rows;
    public static int columns;
    private int totalCells;
    private MainCell[] cell;

    public static Color userColor;
    JTextField speed = new JTextField("250");
    Timer timer = new Timer(250,this);
    String generationText = "Generation: 0";
    JLabel generationLabel = new JLabel(generationText);
    int generation = 0;

    public MainGUI(String title, int r, int c)
    {   
        rows = r;
        columns = c;
        totalCells = r*c;
        System.out.println(totalCells);
        cell = new MainCell[totalCells];

        setTitle(title);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Timer set up
        timer.setInitialDelay(Integer.parseInt(speed.getText()));
        timer.setActionCommand("timer");


        //set up menu bar
        JMenuBar menuBar = new JMenuBar();
        JMenu optionsMenu = new JMenu("Options");
        JMenu aboutMenu = new JMenu("About");
        menuBar.add(optionsMenu);
        menuBar.add(aboutMenu);

        JMenuItem helpButton = new JMenuItem("Help!");
        helpButton.addActionListener(this);
        helpButton.setActionCommand("help");
        aboutMenu.add(helpButton);

        JMenuItem aboutButton = new JMenuItem("About");
        aboutButton.addActionListener(this);
        aboutButton.setActionCommand("about");
        aboutMenu.add(aboutButton);

        JMenuItem colorSelect = new JMenuItem("Select a Custom Color");
        colorSelect.addActionListener(this);
        colorSelect.setActionCommand("colorSelect");
        optionsMenu.add(colorSelect);

        JMenuItem sizeChooser = new JMenuItem("Define a Custom Size");
        sizeChooser.addActionListener(this);
        sizeChooser.setActionCommand("sizeChooser");
        optionsMenu.add(sizeChooser);


        //Create text field to adjust speed and its label
        JPanel speedContainer = new JPanel();
        JLabel speedLabel = new JLabel("Enter the speed of a life cycle (in ms):");
        speedContainer.add(speedLabel);
        speedContainer.add(speed);
        speedContainer.add(generationLabel);
        Dimension speedDim = new Dimension(100,25);
        speed.setPreferredSize(speedDim);


        //Create various buttons
        JPanel buttonContainer = new JPanel();

        JButton randomizerButton = new JButton("Randomize");
        randomizerButton.addActionListener(this);
        randomizerButton.setActionCommand("randomize");
        buttonContainer.add(randomizerButton);

        JButton nextButton = new JButton("Next"); //forces a cycle to occur
        nextButton.addActionListener(this);
        nextButton.setActionCommand("check");
        buttonContainer.add(nextButton);

        JButton startButton = new JButton("Start");
        startButton.addActionListener(this);
        startButton.setActionCommand("start");
        buttonContainer.add(startButton);

        JButton stopButton = new JButton("Stop");
        stopButton.addActionListener(this);
        stopButton.setActionCommand("stop");
        buttonContainer.add(stopButton);

        JButton clearButton = new JButton("Clear");
        clearButton.addActionListener(this);
        clearButton.setActionCommand("clear");
        buttonContainer.add(clearButton);


        //holds the speed container and button container, keeps it neat
        JPanel functionContainer = new JPanel();
        BoxLayout functionLayout = new BoxLayout(functionContainer, BoxLayout.PAGE_AXIS);
        functionContainer.setLayout(functionLayout);
        functionContainer.add(speedContainer);
        speedContainer.setAlignmentX(CENTER_ALIGNMENT);
        functionContainer.add(buttonContainer);
        buttonContainer.setAlignmentX(CENTER_ALIGNMENT);


        //finish up with the cell container
        GridLayout cellLayout = new GridLayout(rows,columns);
        JPanel cellContainer = new JPanel(cellLayout);
        cellContainer.setBackground(Color.black);
        int posX = 0;
        int posY = 0;
        for(int i=0;i<totalCells;i++)
        {
            MainCell childCell = new MainCell();
            cell[i] = childCell;
            childCell.setName(String.valueOf(i));
            childCell.setPosX(posX);
            posX++;
            childCell.setPosY(posY);
            if(posX==columns)
            {
                posX = 0;
                posY++;
            }
            cellContainer.add(childCell);
            childCell.deactivate();
            Graphics g = childCell.getGraphics();
            childCell.paint(g);
        }


        //make a default color
        userColor = Color.yellow;


        //change icon
        URL imgURL = getClass().getResource("images/gol.gif");
        ImageIcon icon = new ImageIcon(imgURL);
        System.out.println(icon);
        setIconImage(icon.getImage());


        //add it all up and pack
        JPanel container = new JPanel();
        BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
        container.setLayout(containerLayout);
        container.add(cellContainer);
        container.add(functionContainer);
        add(menuBar);
        setJMenuBar(menuBar);
        add(container);
        pack();
    }

    private void checkCells()
    {
        //perform check for every cell
        for(int i=0;i<totalCells;i++)
        {
            cell[i].setNeighbors(checkNeighbors(i));
        }
        //use value from check to determine life
        for(int i=0;i<totalCells;i++)
        {
            int neighbors = cell[i].getNeighbors();
            if(cell[i].isActivated())
            {
                System.out.println(cell[i].getName()+" "+neighbors);
                if(neighbors==0||neighbors==1||neighbors>3)
                {
                    cell[i].deactivate();
                }
            }
            if(cell[i].isActivated()==false)
            {
                if(neighbors==3)
                {
                    cell[i].activate();
                }
            }
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        if(e.getActionCommand().equals("randomize"))
        {
            Random rn = new Random();
            for(int i=0;i<totalCells;i++)
            {
                cell[i].deactivate();
                if(rn.nextInt(6)==0)
                {
                    cell[i].activate();
                }
            }
        }



        //help button, self-explanatory
        if(e.getActionCommand().equals("help"))
        {
            JOptionPane.showMessageDialog(this, "The game is governed by four rules:\nFor a space that is 'populated':"
                    + "\n     Each cell with one or no neighbors dies, as if by loneliness."
                    + "\n     Each cell with four or more neighbors dies, as if by overpopulation."
                    + "\n     Each cell with two or three neighbors survives."
                    + "\nFor a space that is 'empty' or 'unpopulated':"
                    + "\n     Each cell with three neighbors becomes populated."
                    + "\nLeft click populates cells. Right click depopulates cells.","Rules:",JOptionPane.PLAIN_MESSAGE);
        }


        //shameless self promotion
        if(e.getActionCommand().equals("about"))
        {
            JOptionPane.showMessageDialog(this, "Game made and owned by *****!"
                    + "\nFree usage as see fit, but give credit where credit is due!\nVERSION: "+version,"About:",JOptionPane.PLAIN_MESSAGE);
        }


        //clears all the cells
        if(e.getActionCommand().equals("clear"))
        {
            timer.stop();
            generation = 0;
            generationText = "Generation: "+generation;
            generationLabel.setText(generationText);
            for(int i=0;i<totalCells;i++)
            {
                cell[i].deactivate();
            }
        }


        //starts timer
        if(e.getActionCommand().equals("start"))
        {

            if(Integer.parseInt(speed.getText())>0)
            {
                timer.setDelay(Integer.parseInt(speed.getText()));
                timer.restart();
            }
            else
            {
                JOptionPane.showMessageDialog(this, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
            }

        }


        //stops timer
        if(e.getActionCommand().equals("stop"))
        {
            timer.stop();
        }


        //run when timer
        if(e.getActionCommand().equals("timer"))
        {
            generation++;
            generationText = "Generation: "+generation;
            generationLabel.setText(generationText);
            timer.stop();
            checkCells();
            timer.setInitialDelay(Integer.parseInt(speed.getText()));
            timer.restart();
        }


        //see checkCells()
        if(e.getActionCommand().equals("check"))
        {
            generation++;
            generationText = "Generation: "+generation;
            generationLabel.setText(generationText);
            checkCells();
        }


        //color select gui
        if(e.getActionCommand().equals("colorSelect"))
        {
            userColor = JColorChooser.showDialog(this, "Choose a color:", userColor);
            if(userColor==null)
            {
                userColor = Color.yellow;
            }
        }


        //size chooser!
        if(e.getActionCommand().equals("sizeChooser"))
        {
            SizeChooser size = new SizeChooser();
            size.setLocationRelativeTo(null);
            size.setVisible(true);
        }
    }

    private int checkNeighbors(int c)
    {
        //if a LIVE neighbor is found, add one
        int neighbors = 0;

        if(cell[c].getPosX()!=0&&cell[c].getPosY()!=0)
        {
            if(c-columns-1>=0)
            {
                if(cell[c-columns-1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c-columns-1].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosY()!=0)
        {
            if(c-columns>=0)
            {
                if(cell[c-columns].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c-columns].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=0)
        {
            if(c-columns+1>=0)
            {
                if(cell[c-columns+1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c-columns+1].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosX()!=0)
        {
            if(c-1>=0)
            {
                if(cell[c-1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c-1].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosX()!=columns-1)
        {
            if(c+1<totalCells)
            {
                if(cell[c+1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c+1].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosX()!=0&&cell[c].getPosY()!=rows-1)
        {
            if(c+columns-1<totalCells)
            {
                if(cell[c+columns-1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c+columns-1].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosY()!=rows-1&&cell[c].getPosY()!=rows-1)
        {
            if(c+columns<totalCells)
            {
                if(cell[c+columns].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c+columns].getName());
                    neighbors++;
                }
            }
        }

        if(cell[c].getPosX()!=columns-1&&cell[c].getPosY()!=rows-1)
        {
            if(c+columns+1<totalCells)
            {
                if(cell[c+columns+1].isActivated())
                {
                    System.out.println(cell[c].getName()+" found "+cell[c+columns+1].getName());
                    neighbors++;
                }
            }
        }
        return neighbors;
    }
}

以下是MainCell.java:

public class MainCell extends JPanel implements MouseListener
{

    //everything here should be self-explanatory

    private static final long   serialVersionUID    = 1761933778208900172L;

    private boolean activated = false;

    public static boolean leftMousePressed;
    public static boolean rightMousePressed;

    private int posX = 0;
    private int posY = 0;
    private int neighbors = 0;

    private URL cellImgURL_1 = getClass().getResource("images/cellImage_1.gif");
    private ImageIcon cellImageIcon_1 = new ImageIcon(cellImgURL_1);
    private Image cellImage_1 = cellImageIcon_1.getImage();

    private URL cellImgURL_2 = getClass().getResource("images/cellImage_2.gif");
    private ImageIcon cellImageIcon_2 = new ImageIcon(cellImgURL_2);
    private Image cellImage_2 = cellImageIcon_2.getImage();

    private URL cellImgURL_3 = getClass().getResource("images/cellImage_3.gif");
    private ImageIcon cellImageIcon_3 = new ImageIcon(cellImgURL_3);
    private Image cellImage_3 = cellImageIcon_3.getImage();

    public MainCell()
    {   
        Dimension dim = new Dimension(17, 17);
        setPreferredSize(dim);
        addMouseListener(this);
    }

    public void activate()
    {
        setBackground(MainGUI.userColor);
        System.out.println(getName()+" "+posX+","+posY+" activated");
        setActivated(true);
    }

    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        if(getPosX()==MainGUI.columns-1&&getPosY()==0)
        {
            //do nothing
        }
        else if(getPosY()!=0&&getPosX()!=MainGUI.columns-1)
        {
            g.drawImage(cellImage_1,0,0,null);
        }
        else if(getPosY()==0)
        {
            g.drawImage(cellImage_2,0,0,null);
        }
        else if(getPosX()==MainGUI.columns-1)
        {
            g.drawImage(cellImage_3,0,0,null);
        }
    }

    public void setActivated(boolean b)
    {
        activated = b;  
    }

    public void deactivate()
    {
        setBackground(Color.gray);
        System.out.println(getName()+" "+posX+","+posY+" deactivated");
        setActivated(false);
    }

    public boolean isActivated()
    {
        return activated;
    }

    public void setNeighbors(int i)
    {
        neighbors = i;
    }

    public int getNeighbors()
    {
        return neighbors;
    }

    public int getPosX()
    {
        return posX;
    }

    public void setPosX(int x)
    {
        posX = x;
    }

    public int getPosY()
    {
        return posY;
    }

    public void setPosY(int y)
    {
        posY = y;
    }

    public void mouseClicked(MouseEvent e)
    {

    }

    public void mouseEntered(MouseEvent e)
    {
        if(leftMousePressed&&SwingUtilities.isLeftMouseButton(e))
        {
            activate();
        }
        if(rightMousePressed&&SwingUtilities.isRightMouseButton(e))
        {
            deactivate();
        }
    }

    public void mouseExited(MouseEvent e)
    {

    }

    public void mousePressed(MouseEvent e)
    {
        if(SwingUtilities.isRightMouseButton(e)&&!leftMousePressed)
        {
            deactivate();
            rightMousePressed = true;
        } 
        if(SwingUtilities.isLeftMouseButton(e)&&!rightMousePressed)
        {
            activate();
            leftMousePressed = true;
        }   
    }

    public void mouseReleased(MouseEvent e)
    {
        if(SwingUtilities.isRightMouseButton(e))
        {
            rightMousePressed = false;
        }
        if(SwingUtilities.isLeftMouseButton(e))
        {
            leftMousePressed = false;
        }
    }

}

以下是 SizeChooser.java:

import java.awt.*;
import java.awt.event.*;
import java.net.URL;

import javax.swing.*;

public class SizeChooser extends JFrame
{
    private static final long   serialVersionUID    = -6431709376438241788L;

    public static MainGUI GUI;

    private static Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    JTextField rowsTextField = new JTextField(String.valueOf((screenSize.height/17)-15));
    JTextField columnsTextField = new JTextField(String.valueOf((screenSize.width/17)-10));

    private static int rows = screenSize.height/17-15;
    private static int columns = screenSize.width/17-10;

    public SizeChooser()
    {
        setResizable(false);
        setTitle("Select a size!");

        JPanel container = new JPanel();
        BoxLayout containerLayout = new BoxLayout(container, BoxLayout.PAGE_AXIS);
        container.setLayout(containerLayout);
        add(container);

        JLabel rowsLabel = new JLabel("Rows:");
        container.add(rowsLabel);
        container.add(rowsTextField);

        JLabel columnsLabel = new JLabel("Columns:");
        container.add(columnsLabel);
        container.add(columnsTextField);

        JButton confirmSize = new JButton("Confirm");
        confirmSize.addActionListener(new ActionListener()
        {

            public void actionPerformed(ActionEvent e)
            {
                GUI.setVisible(false);
                GUI = null;
                if(Integer.parseInt(rowsTextField.getText())>0)
                {
                    rows = Integer.parseInt(rowsTextField.getText());
                }
                else
                {
                    JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
                }
                if(Integer.parseInt(columnsTextField.getText())>0)
                {
                     columns = Integer.parseInt(columnsTextField.getText());
                }
                else
                {
                    JOptionPane.showMessageDialog(rootPane, "Please use a value greater than 0!","Rules:",JOptionPane.ERROR_MESSAGE);
                }
                GUI = new MainGUI("The Game of Life!", rows, columns);
                GUI.setLocationRelativeTo(null);
                GUI.setVisible(true);
                setVisible(false);
            }           
        });
        container.add(confirmSize);

        URL imgURL = getClass().getResource("images/gol.gif");
        ImageIcon icon = new ImageIcon(imgURL);
        System.out.println(icon);
        setIconImage(icon.getImage());
        pack();
    }


    public static void main(String[]args)
    {
        GUI = new MainGUI("The Game of Life!", rows, columns);
        GUI.setLocationRelativeTo(null);
        GUI.setVisible(true);
    }

}

所以现在的问题是,当按下随机化按钮,或者存在大量单元格然后启动计时器时,单元格不像活动较少的单元格那样活泼。例如,对于 100 列和 50 行,当按下随机按钮时,一个单元格激活,然后是下一个单元格,然后是另一个单元格,依此类推。我可以让它们同时激活吗?这只是一次计算太多东西的问题吗?并发会有帮助吗?

快速编辑:摇摆计时器是这个项目的最佳创意吗?

4

2 回答 2

0

我还没有完全阅读您的代码,但我猜您的侦听器方法计算量相当大,因此更新显示滞后。

于 2013-11-07T02:19:04.983 回答
0

This simple test reveals that your randomize operation should be fairly quick:

public static void main(String args[]) {
    Random rn = new Random();
    boolean b[] = new boolean[1000000];

    long timer = System.nanoTime();
    for (int i = 0; i < b.length; i++) {
        b[i] = rn.nextInt(6) == 0;
    }
    timer = System.nanoTime() - timer;
    System.out.println(timer + "ns / " + (timer / 1000000) + "ms");
}

The output for me is:

17580267ns / 17ms

So this leads me into thinking activate() or deactivate() is causing your UI to be redrawn.


I am unable to run this because I don't have your graphical assets, but I would try those changes to see if it works:

In MainGUI#actionPerformed, change:

if(e.getActionCommand().equals("randomize"))
{
    Random rn = new Random();
    for(int i=0;i<totalCells;i++)
    {
        cell[i].deactivate();
        if(rn.nextInt(6)==0)
        {
            cell[i].activate();
        }
    }
}

to:

if(e.getActionCommand().equals("randomize"))
{
    Random rn = new Random();
    for(int i=0;i<totalCells;i++)
    {
        // This will not cause the object to be redrawn and should
        // be a fairly cheap operation
        cell[i].setActivated(rn.nextInt(6)==0);
    }
    // Cause the UI to repaint
    repaint();
}

Add this to MainCell

// You can specify those colors however you like
public static final Color COLOR_ACTIVATED = Color.RED;
public static final Color COLOR_DEACTIVATED = Color.GRAY;

And change:

protected void paintComponent(Graphics g)
{
    super.paintComponent(g);
    if(getPosX()==MainGUI.columns-1&&getPosY()==0)
    {
        //do nothing
    }

to:

protected void paintComponent(Graphics g)
{
    // We now make UI changes only when the component is painted
    setBackground(activated ? COLOR_ACTIVATED : COLOR_DEACTIVATED);
    super.paintComponent(g);
    if(getPosX()==MainGUI.columns-1&&getPosY()==0)
    {
        //do nothing
    }
于 2013-11-07T08:31:29.457 回答