如何等待 MouseListener 鼠标按下?
How to wait for a MouseListener mouse press?
所以,我知道以前有人问过这个问题,但这些答案不适用于我程序的当前结构。我有一个井字游戏。在游戏算法中,当轮到用户时,我让它调用一种方法来获取鼠标点击的 X 和 Y 坐标。但是,我希望这种方法首先提示用户点击,然后等待用户点击,然后获取点击的 x 和 y 供游戏算法使用。目前,它只是拉动最后一次点击的 x 和 y,没有时间让用户在轮到他们时点击。我必须解决这个问题的唯一想法是 运行 游戏和用户代码在 2 个线程上并且有一个睡眠。但是,这似乎过于复杂,我不想这样做。整个情况似乎是一个非常基本的问题,在执行代码之前等待鼠标单击。我该怎么做呢?
void takeTurn() {
//turnCount++;
while(gameOver == false) {
if (turn == 'O') {
O.getInput();
if(board[O.x][O.y] != '\u0000') continue;
board[O.x][O.y] = 'O';
}
else if (turn == 'X') {
X.getInput();
if(board[X.x][X.y] != '\u0000') continue;
board[X.x][X.y] = 'X';
}
printBoard();
if (checkWinner(turn) == turn) {
System.out.println("Winner: " + turn);
}
if (turn == 'O') turn = 'X';
else if (turn == 'X') turn = 'O';
}
}
编辑:
getInput() 是获取 x 和 y 的方法。
public void getInput() {
System.out.println("Click on your tile");
//wait for click here
//then get x & y of click
}
编辑:
好的,那么使用 ActionListener,我如何让线程等待直到执行动作?
你把它倒过来了,不是说你需要等待输入。你需要做的是点击鼠标时的一个动作。说所有其他问题仍然回答你想做的事情。你可以关注https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html and come up with a solution. Another good example is Java MouseListener
关键不是"wait"鼠标输入,而是根据程序的状态将程序的行为更改为鼠标按下。例如,如果你在玩井字游戏,你会想给程序一个变量让它知道轮到谁了,这可以是一个简单的布尔变量,比如
private boolean xTurn = true;
当这个变量为真时,轮到X,为假时,轮到O。
然后在您的 MouseListener(如果是 Swing 应用程序)中,使用变量来帮助决定要做什么,然后在使用它之后,将布尔值切换到下一个状态。例如:
// within mouse listener
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// toggle value held by boolean variable.
xTurn = !xTurn;
例如:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@SuppressWarnings("serial")
public class TicTacToePanel extends JPanel {
private static final int ROWS = 3;
private static final int MY_C = 240;
private static final Color BG = new Color(MY_C, MY_C, MY_C);
private static final int PTS = 60;
private static final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, PTS);
public static final Color X_COLOR = Color.BLUE;
public static final Color O_COLOR = Color.RED;
private JLabel[][] labels = new JLabel[ROWS][ROWS];
private boolean xTurn = true;
public TicTacToePanel() {
setLayout(new GridLayout(ROWS, ROWS, 2, 2));
setBackground(Color.black);
MyMouse myMouse = new MyMouse();
for (int row = 0; row < labels.length; row++) {
for (int col = 0; col < labels[row].length; col++) {
JLabel label = new JLabel(" ", SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(BG);
label.setFont(FONT);
add(label);
label.addMouseListener(myMouse);
}
}
}
private class MyMouse extends MouseAdapter {
@Override // override mousePressed not mouseClicked
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
String text = label.getText().trim();
if (!text.isEmpty()) {
return;
}
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// information to help check for win
int chosenX = -1;
int chosenY = -1;
for (int x = 0; x < labels.length; x++) {
for (int y = 0; y < labels[x].length; y++) {
if (labels[x][y] == label) {
chosenX = x;
chosenY = y;
}
}
}
// TODO: check for win here
xTurn = !xTurn;
}
}
private static void createAndShowGui() {
TicTacToePanel mainPanel = new TicTacToePanel();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
所以,我知道以前有人问过这个问题,但这些答案不适用于我程序的当前结构。我有一个井字游戏。在游戏算法中,当轮到用户时,我让它调用一种方法来获取鼠标点击的 X 和 Y 坐标。但是,我希望这种方法首先提示用户点击,然后等待用户点击,然后获取点击的 x 和 y 供游戏算法使用。目前,它只是拉动最后一次点击的 x 和 y,没有时间让用户在轮到他们时点击。我必须解决这个问题的唯一想法是 运行 游戏和用户代码在 2 个线程上并且有一个睡眠。但是,这似乎过于复杂,我不想这样做。整个情况似乎是一个非常基本的问题,在执行代码之前等待鼠标单击。我该怎么做呢?
void takeTurn() {
//turnCount++;
while(gameOver == false) {
if (turn == 'O') {
O.getInput();
if(board[O.x][O.y] != '\u0000') continue;
board[O.x][O.y] = 'O';
}
else if (turn == 'X') {
X.getInput();
if(board[X.x][X.y] != '\u0000') continue;
board[X.x][X.y] = 'X';
}
printBoard();
if (checkWinner(turn) == turn) {
System.out.println("Winner: " + turn);
}
if (turn == 'O') turn = 'X';
else if (turn == 'X') turn = 'O';
}
}
编辑: getInput() 是获取 x 和 y 的方法。
public void getInput() {
System.out.println("Click on your tile");
//wait for click here
//then get x & y of click
}
编辑: 好的,那么使用 ActionListener,我如何让线程等待直到执行动作?
你把它倒过来了,不是说你需要等待输入。你需要做的是点击鼠标时的一个动作。说所有其他问题仍然回答你想做的事情。你可以关注https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html and come up with a solution. Another good example is Java MouseListener
关键不是"wait"鼠标输入,而是根据程序的状态将程序的行为更改为鼠标按下。例如,如果你在玩井字游戏,你会想给程序一个变量让它知道轮到谁了,这可以是一个简单的布尔变量,比如
private boolean xTurn = true;
当这个变量为真时,轮到X,为假时,轮到O。
然后在您的 MouseListener(如果是 Swing 应用程序)中,使用变量来帮助决定要做什么,然后在使用它之后,将布尔值切换到下一个状态。例如:
// within mouse listener
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// toggle value held by boolean variable.
xTurn = !xTurn;
例如:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@SuppressWarnings("serial")
public class TicTacToePanel extends JPanel {
private static final int ROWS = 3;
private static final int MY_C = 240;
private static final Color BG = new Color(MY_C, MY_C, MY_C);
private static final int PTS = 60;
private static final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, PTS);
public static final Color X_COLOR = Color.BLUE;
public static final Color O_COLOR = Color.RED;
private JLabel[][] labels = new JLabel[ROWS][ROWS];
private boolean xTurn = true;
public TicTacToePanel() {
setLayout(new GridLayout(ROWS, ROWS, 2, 2));
setBackground(Color.black);
MyMouse myMouse = new MyMouse();
for (int row = 0; row < labels.length; row++) {
for (int col = 0; col < labels[row].length; col++) {
JLabel label = new JLabel(" ", SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(BG);
label.setFont(FONT);
add(label);
label.addMouseListener(myMouse);
}
}
}
private class MyMouse extends MouseAdapter {
@Override // override mousePressed not mouseClicked
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
String text = label.getText().trim();
if (!text.isEmpty()) {
return;
}
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// information to help check for win
int chosenX = -1;
int chosenY = -1;
for (int x = 0; x < labels.length; x++) {
for (int y = 0; y < labels[x].length; y++) {
if (labels[x][y] == label) {
chosenX = x;
chosenY = y;
}
}
}
// TODO: check for win here
xTurn = !xTurn;
}
}
private static void createAndShowGui() {
TicTacToePanel mainPanel = new TicTacToePanel();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}