【问题标题】:Game Of Life Java MouseAdapter doesn't always workGame Of Life Java MouseAdapter 并不总是有效
【发布时间】:2013-05-16 00:46:09
【问题描述】:

有时mousePressed 事件会被执行,但有时不会。它似乎也取决于你按下它的时间。如何让它始终正常工作?

我不确定代码的哪一部分有问题,所以这是整个类:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import java.util.Random;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener {
    Timer timer = new Timer(500, this);

    private boolean[][] board;
    private boolean isActive = false;
    private int height;
    private int width;
    private int multiplier = 20;

    private JButton btnRun;
    private JButton btnRand;
    private JButton btnClear;

    public Board() {
        this(new boolean[20][20]);
    }

    public Board(final boolean[][] board) {
        this.board = board;
        height = board.length;
        width = board[0].length;
        setBackground(Color.black);
        btnRun = new JButton("Run");
        add(btnRun);
        btnRun.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                isActive = !isActive;
                btnRun.setText(isActive ? "Pause" : "Run");
            }
        });
        btnRand = new JButton("Random");
        add(btnRand);
        btnRand.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setBoard(randomBoard());
            }
        });
        btnClear = new JButton("Clear");
        add(btnClear);
        btnClear.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                setBoard(clearBoard());
            }
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
            }
        });
        timer.start();
    }

    public int getMultiplier() {
        return multiplier;
    }

    public boolean[][] getBoard() {
        return board;
    }

    public void setBoard(boolean[][] boardToSet) {
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                board[i][j] = boardToSet[i][j];
            }
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                g.setColor(board[i][j] ? Color.green : Color.gray);
                g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
            }
        }
        if (isActive) {
            timer.start();
        }
        else {
            timer.stop();
            repaint();
        }
    }

    public void actionPerformed(ActionEvent e) {
        board = nextGeneration();
        repaint();
    }

    public boolean[][] randomBoard() {
        Random rand = new Random();
        boolean[][] randBoard = new boolean[height][width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                randBoard[i][j] = rand.nextBoolean();
            }
        }
        return randBoard;
    }

    public boolean[][] clearBoard() {
        boolean[][] emptyBoard = new boolean[height][width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                emptyBoard[i][j] = false;
            }
        }
        return emptyBoard;
    }

    public int countSurrounding(int a, int b) {
        int count = 0;
        int[][] surrounding = {{a - 1, b - 1},
                               {a - 1, b    },
                               {a - 1, b + 1},
                               {a    , b - 1},
                               {a    , b + 1},
                               {a + 1, b - 1},
                               {a + 1, b    },
                               {a + 1, b + 1}};
        for (int[] i: surrounding) {
            try {
                if (board[i[0]][i[1]]) {
                    count++;
                }
            }
            catch (ArrayIndexOutOfBoundsException e) {}
        }
        return count;
    }

    public boolean[][] nextGeneration() {
        boolean[][] nextBoard = new boolean[height][width];
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                nextBoard[i][j] = board[i][j];
            }
        }
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                if (board[i][j] && !(countSurrounding(i, j) == 2 || countSurrounding(i, j) == 3)) {
                    nextBoard[i][j] = false;
                }
                else if (!board[i][j] && countSurrounding(i, j) == 3) {
                    nextBoard[i][j] = true;
                }
            }
        }
        return nextBoard;
    }   
}

【问题讨论】:

  • 无需粘贴两次代码..
  • 可能是getBoard()[e.getY() / multiplier][e.getX() / multiplier]中的四舍五入
  • @whiskeyspider 这是一个稍微不同的问题
  • @Lewis,如果你在论坛上浪费别人的时间,因为你不听其他帖子中给出的建议,这很烦人。在发表此评论时,有 34 人花时间阅读了此问题。有几个人花时间回答并重复您之前发布的建议。这段时间可以更好地帮助其他真正需要帮助的人。

标签: java swing awt mouselistener


【解决方案1】:

mousePressed()中添加一个System.out语句,你会看到它总是被调用:

    public void mousePressed(MouseEvent e) {
        System.out.println("mousePressed");
        getBoard()[e.getY() / multiplier][e.getX() / multiplier] = !getBoard()[e.getY() / multiplier][e.getX() / multiplier];
        repaint();
    }

与您在other very similar question 中建议的其他人一样,问题源于您在绘制方法中使用了计时器。

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            g.setColor(board[i][j] ? Color.green : Color.gray);
            g.fillRect(j * multiplier, i * multiplier, multiplier - 1, multiplier - 1);
        }
    }
    //if (isActive) {  // take this stuff out...
    //    timer.start();
    //}
    //else {
    //    timer.stop();
    //    repaint();
    //}
}

paintComponent() 方法只能用于绘制组件。不要使用它来启动/停止计时器,对repaint() 进行额外调用,或以其他方式调用任何其他类型的程序逻辑。重新思考你的设计,尤其是在paintComponent()

【讨论】:

  • 主要问题可能是 if (isActive) { 并通过测试 Timer.isRunning 来避免同时出现多个实例
【解决方案2】:

除了whiskeyspider所说的,如果你在一个单元格运行的时候点击它,你不会看到这个单元格在下一代之前点亮,并且只有当那个位置被认为是活着的,在处理之后,在下一代.

【讨论】:

    猜你喜欢
    • 2022-12-26
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2015-05-07
    • 2012-04-15
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    相关资源
    最近更新 更多