【发布时间】:2014-05-29 03:50:53
【问题描述】:
我在使用 Java swing 的 Timer 功能时遇到了一些问题。我对使用 Java 编程相当陌生,因此非常感谢任何帮助。我查看了该站点上的许多其他 Timer 问题,但没有一个回答我的问题。我制作了一个 GUI,允许您玩石头剪刀布,您可以在其中单击三个按钮进行选择。我希望我的程序在您单击按钮后休眠大约 1 秒钟,然后在它显示一条消息后再次休眠。在我意识到 Thread.sleep() 不适用于我的 GUI 之后,我尝试实现一个计时器。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
import java.io.*;
public class rps {
//ROCK PAPER SCISSORS
static JLabel middle = new JLabel();
static JLabel them = new JLabel();
static JLabel yourWins = new JLabel();
static JLabel theirWins = new JLabel();
static JPanel yourPanel = new JPanel();
static JPanel middlePanel = new JPanel();
static JLabel blank1 = new JLabel();
static JLabel blank2 = new JLabel();
static JButton rock = new JButton("Rock");
static JButton paper = new JButton("Paper");
static JButton scissors = new JButton("Scissors");
static int yw = 0;
static int tw = 0;
static ButtonHandler listener = new ButtonHandler();
public static void main(String[] args) {
//Create the frame
JFrame frame = new JFrame("Rock Paper Scissors");
frame.setSize(500, 500); //Setting the size of the frame
middle.setFont(new Font("Serif", Font.PLAIN, 30));
middle.setHorizontalAlignment(SwingConstants.CENTER);
them.setFont(new Font("Serif", Font.PLAIN, 15));
them.setHorizontalAlignment(SwingConstants.CENTER);
yourWins.setHorizontalAlignment(SwingConstants.CENTER);
theirWins.setHorizontalAlignment(SwingConstants.CENTER);
//Creating panels
JPanel bigPanel = new JPanel();
Border border = BorderFactory.createLineBorder(Color.BLACK, 1);
Border wlb = BorderFactory.createLineBorder(Color.RED, 1);
them.setBorder(border);
yourPanel.setBorder(border);
bigPanel.setBorder(border);
yourWins.setBorder(wlb);
theirWins.setBorder(wlb);
middlePanel.setBorder(border);
//Creating grid layouts
GridLayout yourGrid = new GridLayout(1,3,10,10);
GridLayout theirGrid = new GridLayout(1,1); //One row, one column
GridLayout middleGrid = new GridLayout(5,1);
GridLayout bigGrid = new GridLayout(3,1);//Two rows, one column
//Setting the layouts of each panel to the grid layouts created above
yourPanel.setLayout(yourGrid); //Adding layout to buttons panel
them.setLayout(theirGrid); //Adding layout to label panel
middlePanel.setLayout(middleGrid);
bigPanel.setLayout(bigGrid);
//Adding r/p/s to your grid.
yourPanel.add(rock);
yourPanel.add(paper);
yourPanel.add(scissors);
//Adding w/l rations to middlegrid.
middlePanel.add(theirWins);
middlePanel.add(blank1);
middlePanel.add(middle);
middlePanel.add(blank2);
middlePanel.add(yourWins);
//Attaching the listener to all the buttons
rock.addActionListener(listener);
paper.addActionListener(listener);
scissors.addActionListener(listener);
bigPanel.add(them);
bigPanel.add(middlePanel);
bigPanel.add(yourPanel);
//Shows the score at 0-0.
yourWins.setText("Your wins: " + yw);
theirWins.setText("Their wins: " + tw);
frame.getContentPane().add(bigPanel); //panel to frame
frame.setVisible(true); // Shows frame on screen
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
//Class represents what do when a button is pressed
private static class ButtonHandler implements ActionListener {
public void actionPerformed (ActionEvent e) {
Timer timer = new Timer(1000, this);
String tc = random();
them.setText("They chose: " + tc + "!");
if (e.getSource() == rock) {
whoWins("rock", tc);
} else if (e.getSource() == paper) {
whoWins("paper", tc);
} else if (e.getSource() == scissors) {
whoWins("scissors", tc);
}
yourWins.setText("Your wins: " + yw);
theirWins.setText("Their wins: " + tw);
timer.setRepeats(false);
timer.start();
}
}
public static String random() {
int random = (int) (Math.random() * 3);
if (random == 0) {
return "Rock";
} else if (random == 1) {
return "Paper";
} else if (random == 2) {
return "Scissors";
}
return "";
}
public static void whoWins(String yc, String tc) {
if (yc.equals("rock")) {
if (tc.equals("Rock")) {
middle.setText("It's a tie!");
} else if (tc.equals("Paper")) {
middle.setText("You lose!");
tw++;
} else if (tc.equals("Scissors")) {
middle.setText("You win!");
yw++;
}
} else if (yc.equals("paper")) {
if (tc.equals("Rock")) {
middle.setText("You win!");
yw++;
} else if (tc.equals("Paper")) {
middle.setText("It's a tie!");
} else if (tc.equals("Scissors")) {
middle.setText("You lose!");
tw++;
}
} else if (yc.equals("scissors")) {
if (tc.equals("Rock")) {
middle.setText("You lose!");
tw++;
} else if (tc.equals("Paper")) {
middle.setText("You win!");
yw++;
} else if (tc.equals("Scissors")) {
middle.setText("It's a tie!");
}
}
}
}
实际发生的情况是从我按下按钮到显示消息没有延迟,因为显然我没有正确使用计时器。我希望计时器只运行一次,运行后代码将执行。但是,当我单击一个按钮时,尽管 setRepeats 为 false,但计时器将重复运行。因此,我想显示的消息不会被延迟,而是会立即显示,但随后会循环显示一条消息(消息是随机的),直到我关闭程序。如果我再次单击该按钮,它将使计时器的速度增加一倍,并且消息显示的速度增加一倍,依此类推。
them.setText("They chose: " + tc + "!");
这是重复显示的消息,变量 tc 每次都在变化。计时器似乎只是在每个计时器间隔 (1s) 显示此消息。
任何帮助将不胜感激。
编辑:
所以我添加了这个部分:
private static class ButtonHandler implements ActionListener {
public void actionPerformed (ActionEvent e) {
// I'd be disabling the buttons here to prevent
// the user from trying to trigger another
// update...
// This is an instance field which is used by your
// listener
Timer timer = new Timer(1000, listenert);
timer.setRepeats(false);
timer.start();
}
}
private static class timer implements ActionListener {
public void actionPerformed (ActionEvent e) {
String tc = random(); //A method that chooses a random word.
them.setText("They chose: " + tc + "!");
if (e.getSource() == rock) {
whoWins("rock", tc); //whoWins is a method that will display a message.
} else if (e.getSource() == paper) {
whoWins("paper", tc);
} else if (e.getSource() == scissors) {
whoWins("scissors", tc);
}
yourWins.setText("Your wins: " + yw);
theirWins.setText("Their wins: " + tw);
// Start another Timer here that waits 1 second
// and re-enables the other buttons...
}
}
所以我相信现在发生的事情是,当我单击一个按钮时,按钮处理程序侦听器会启动附加到计时器侦听器(名为 listenert)的计时器,该计时器将运行计时器类的 actionPerformed 中的代码。但是睡眠功能仍然不起作用
编辑 2.5:
private static class ButtonHandler implements ActionListener {
public void actionPerformed (ActionEvent e) {
final JButton button = (JButton)e.getSource();
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
String tc = random();
them.setText("They chose: " + tc + "!");
if (button == rock) {
whoWins("rock", tc);
} else if (button == paper) {
whoWins("paper", tc);
} else if (button == scissors) {
whoWins("scissors", tc);
}
yourWins.setText("Your wins: " + yw);
theirWins.setText("Their wins: " + tw);
}
});
timer.setRepeats(false);
timer.start();
}
}
这就是我目前所拥有的,我只需要在之后添加antoher sleep them.setText("他们选择了:" + tc + "!"); 如果有的话,我会把 timer.restart() 放在哪里? timer.start() 在我不太明白的方法的末尾。
【问题讨论】:
-
您可以在 MadProgrammer 的
TestPane示例中看到他如何创建一个匿名类ActionListener作为参数传递给Timer。考虑那个,因为您的计时器侦听器不应与ButtonListener(用于按钮)相同。将这个想法与他的其他答案结合起来,并尝试解决它。重点不是给你完整的答案,而是让你了解计时器应该如何工作:-) -
你不需要额外的监听器。只需执行
new Timer(1000, new ActionListener() { ... });。尝试并工作。如果您遇到困难,请发布您的尝试的另一个编辑:-) -
我应该在这些括号内插入按下按钮时会发生什么或进行某种计时器操作吗?
-
不完全确定您期望的结果,但是是的,但您还需要
actionPerformed。传递给 Timer 的 ActionListener 的目的是在延迟后执行您想要执行的操作。所以你想在延迟之后执行什么,这就是计时器监听器应该做的事情 -
好的,我已经进行了编辑,感谢你们两个,我想我已经取得了进展。它现在可以正确执行延迟,然后显示消息,但这次不会在延迟和 FIRST 消息之后设置中间文本。