Swing计时器仅在最后一个事件上运行

时间:2014-10-18 14:07:04

标签: java swing timer

我正在尝试建立一个西蒙说的游戏,它会闪烁按下按钮。我目前正在尝试研究如何使按钮一个接一个地闪烁。在文档之后(尽我所能),我编写了下面的代码,但由于某种原因,只有绿色按钮闪烁。我进一步测试了一下,发现只有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
        }
    }

2 个答案:

答案 0 :(得分:3)

要记住以下几点:

  • Swing是单线程的(线程称为E(vent)D(ispatch)T(hread))。当您在该线程上执行操作时,您的UI无法重新绘制,反之亦然。
  • 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();
            }
        });
    }
}