我正在尝试建立一个西蒙说的游戏,它会闪烁按下按钮。我目前正在尝试研究如何使按钮一个接一个地闪烁。在文档之后(尽我所能),我编写了下面的代码,但由于某种原因,只有绿色按钮闪烁。我进一步测试了一下,发现只有btnGo
事件中的最后一个方法可以正常工作。我认为它与定时器运行的方式有关,它在定时器完成之前将红色和蓝色按钮变回黑色,但我不确定如何或为什么?
public void flashRed(){
btn1.setBackground(Color.red);
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashYellow(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.yellow);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashGreen(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.green);
btn4.setBackground(Color.black);
repaint();
t.start();
}
public void flashBlue(){
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.blue);
repaint();
t.start();
}
@Override
public void actionPerformed(ActionEvent event) {
if(event.getSource() == btnGo)
{
flashRed();
flashBlue();
flashGreen();
}
if(event.getSource() ==t){
btn1.setBackground(Color.black); //resets btn1 to black
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
repaint();
t.stop(); //stops the timer
}
}
答案 0 :(得分:3)
要记住以下几点:
repaint()
的调用实际上并不执行重绘。它只是在EDT上安排一个重绘。如果安排了多个重新绘制,则只需对它们进行分组,只执行一次JComponents
上的大多数方法都不会立即更改组件。他们只是更改该组件的状态并安排重新绘制。重绘完成后,您会看到您在UI中反映的更改。那么当您按JButton
并触发ActionListener
时会发生什么:
flashRed();
flashBlue();
flashGreen();
这将改变许多按钮的背景颜色,但由于代码占用了EDT,因此根本没有时间执行重绘。只有当您的ActionListener
完成后,才能执行repaint
。此时,除绿色按钮外,所有按钮的背景都变回黑色。这就是为什么你只看到绿色按钮闪烁。
解决这个问题需要做的是逐个闪烁并在两者之间释放EDT,让它有时间进行重绘。我会用Timer
来解决这个问题。但是为什么你只使用它来将按钮的背景恢复为黑色,我也会用它来闪烁。
在伪代码中,ActionListener
看起来像:
switch ( iteration ){
case first:
flashRed();
increaseIteration();
break;
case second:
flashBlue();
increaseIteration();
break;
...
case last:
restoreAllToBlack();
timer.stop();
break;
}
答案 1 :(得分:-1)
您需要在后台线程中完成所有等待,然后将颜色更改命令放入EDT中,稍后再调用。如果你这样做,那么你可以完全取消定时器构造,因为你可以只睡眠()后台线程。可以这样想,后台线程正在编排颜色变化,EDT处理实际的屏幕小部件:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
public class testFrame {
static JButton btn1 = new JButton("red");
static JButton btn2 = new JButton("yellow");
static JButton btn3 = new JButton("green");
static JButton btn4 = new JButton("blue");
public static void showFrame() {
JFrame frame = new JFrame();
frame.setLocation(500, 500);
frame.setSize(100, 100);
final JButton button = new JButton("Test");
button.setMaximumSize(new Dimension(80, 30));
button.setSize(80, 20);
frame.setLayout(new GridLayout(5, 1));
frame.add(button);
frame.add(btn1);
frame.add(btn2);
frame.add(btn3);
frame.add(btn4);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
@Override
public Void doInBackground() {
try {
flashRed();
Thread.sleep(500);
flashGreen();
Thread.sleep(500);
flashBlue();
Thread.sleep(500);
flashYellow();
} catch (InterruptedException e) {
}
return null;
}
@Override
public void done() {
}
};
worker.execute();
}
});
frame.pack();
frame.setVisible(true);
}
public static void flashRed() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
btn1.setBackground(Color.red);
btn2.setBackground(Color.black);
btn4.setBackground(Color.black);
btn3.setBackground(Color.black);
}
});
}
public static void flashYellow() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
btn1.setBackground(Color.black);
btn2.setBackground(Color.yellow);
btn3.setBackground(Color.black);
btn4.setBackground(Color.black);
}
});
}
public static void flashGreen() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.green);
btn4.setBackground(Color.black);
}
});
}
public static void flashBlue() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
btn1.setBackground(Color.black);
btn2.setBackground(Color.black);
btn3.setBackground(Color.black);
btn4.setBackground(Color.blue);
}
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
showFrame();
}
});
}
}