在while循环中等待用户操作 - JAVA

时间:2011-05-29 09:23:52

标签: java events loops listener

我正在写一个Reversi应用程序。我实现了转换管理器类,但我在while循环中遇到了一些问题。

这是我的代码:

while (!table.isFull() || passFlag != 2) {
    if (player1.isActive()) {
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                if (e.getSource() instanceof Field) {
                                    ((Field) e.getSource()).changeToBlack();
                                }
                            }
                        });
            }
        }
    }
    if (player2.isActive()) {
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                if (e.getSource() instanceof Field) {
                                    ((Field) e.getSource()).changeToWhite();
                                }
                            }
                        });
            }
        }
    }
    sentinel.changeActivePlayer(player1, player2);

该表是按钮网格,字段是按钮。循环不等待玩家互动。如何实现代码以便等待用户单击鼠标?

这是此类的完整代码

package Core;

import GUILayer.Field;
import GUILayer.MainFrame;
import elements.Player;
import elements.Table;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TurnManager {

    int passFlag = 0;
    int TurnFlag = 0;
    Sentinel sentinel = new Sentinel();

    public TurnManager() {
    }

    public void manage(MainFrame mainframe, Table table, Player player1, Player player2) {

        while (!table.isFull() || passFlag != 2) {
            if (player1.isActive()) {
                for (int i = 0; i < table.getSize(); i++) {
                    for (int j = 0; j < table.getSize(); j++) {
                        table.getField(i, j).addActionListener(
                                new ActionListener() {

                                    public void actionPerformed(ActionEvent e) {
                                        if (e.getSource() instanceof Field) {
                                            ((Field) e.getSource()).changeToBlack();
                                        }
                                    }
                                });
                    }
                }
            }
            if (player2.isActive()) {
                for (int i = 0; i < table.getSize(); i++) {
                    for (int j = 0; j < table.getSize(); j++) {
                        table.getField(i, j).addActionListener(
                                new ActionListener() {

                                    public void actionPerformed(ActionEvent e) {
                                        if (e.getSource() instanceof Field) {
                                            ((Field) e.getSource()).changeToWhite();
                                        }
                                    }
                                });
                    }
                }
            }
            sentinel.changeActivePlayer(player1, player2);
        }
    }
}

3 个答案:

答案 0 :(得分:4)

我同意霍华德评论......这看起来非常错误。使用侦听器和事件意味着您(大多数时候)不必自己使用事件循环。

尝试以下操作:创建一个包含您的电路板的类。董事会知道每个领域的颜色(以及它需要知道的其他一切)。初始化GUI时,创建单个 EventListener,调用板对象的某些方法。这个方法被传递了被点击的字段(我想它被点击了,或者我错了?)。您将此EventListener的引用存储在变量中。然后循环遍历每个for和column,并将此侦听器附加到每个字段。然后显示GUI。

让我澄清一下:所有这些都是在初始化时完成的。

答案 1 :(得分:0)

一些建议:

  • 如前所述,不需要你的while循环,拥有它们(即使它们确实有效)会使你的代码不受事件驱动。
  • 您想要将模型与视图分开。该模型 - 应该对视图一无所知 - 将知道它是谁。它将有一个非静态字段,告诉它轮到它,枚举适用于此,当更改术语时,该字段的值会发生变化。
  • 每个单元格都会附加一个监听器(或“控制”),可能是同一个监听器(根据Martin的帖子 - 为他+1),而听众唯一的工作就是告诉模型单击了哪个单元格,通过在侦听器的Event参数上调用getSource可以获得的信息。如果监听器是一个ActionListener,我正在谈论的事件将是传递给监听器的actionPerformed方法的ActionEvent对象。
  • 然后,模型将决定如何处理信息,如果有的话,根据按下哪个细胞以及轮到哪个细胞。
  • 视图(GUI)将监听模型更改,可能使用PropertyChangeListener或您自己创建的另一个侦听器,并将根据模型的状态更改其显示。

答案 2 :(得分:0)

这不是一个完整的解决方案,但您的代码看起来应该更像这样。我认为将这些东西放在一起是一个很好的起点。希望这会有所帮助。

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class TurnManager implements ActionListener{

    int passFlag = 0;
    int TurnFlag = 0;
    Sentinel sentinel = new Sentinel();
    Player player1,player2;


    public TurnManager(MainFrame mainframe, Table table, Player p1, Player p2) {
        player1 = p1;
        player2 = p2;
        for (int i = 0; i < table.getSize(); i++) {
            for (int j = 0; j < table.getSize(); j++) {
                table.getField(i, j).addActionListener(this);
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() instanceof Field) {
            Field field = ((Field) e.getSource());
            //implement logic here, for example:
            if (table.isFull())
                throw new RuntimeException("Table full! Stop! STOP!");

            if (player1.isActive())
                field.changeToBlack();
            if (player2.isActive())
                field.changeToBlack();
        }
    }
}