西蒙的闪烁按钮说

我正在制作一个Simon说的程序,我需要按钮在生成随机模式时闪烁,以便用户知道要输入什么。 我的问题是我不能让我的按钮(JButtons是图像)闪烁,我的逻辑是两个按钮在彼此的顶部,一个可见,而不是然后切换按钮可见性,等待一秒然后再改回来。 我试过使用Thread.sleep(),wait(),甚至繁忙的循环等待,但没有一个工作。 我被告知摇摆计时器是我最好的选择,这就是我想要使用的。 此外,我希望按钮在单击开始按钮后开始闪烁。

public class GamePanel extends JPanel implements ActionListener { private JButton greenButton; private JButton startButton; private JButton greenBlinkButton; private GridBagConstraints gbc; private Timer buttonTimer; GamePanel() { gbc = new GridBagConstraints(); GridBagLayout grid = new GridBagLayout(); setLayout(grid); //GridBag location lets startButton = new JButton("Start"); gbc.gridx = 0; gbc.gridy = 0; add(startButton, gbc); startButton.setPreferredSize(new Dimension(200,30)); greenReg = new ImageIcon("src/Images/Green Button.png"); greenBlink = new ImageIcon("src/Images/Blink Green Button.png"); greenButton = new JButton(new ImageIcon(greenReg)); gbc.gridx = 0; gbc.gridy = 1; add(greenButton, gbc); add(greenBlinkButton, gbc); startButton.addActionListener(this); //Timer buttonTimer = new Timer(500, this); } @Override public void actionPerformed(ActionEvent e) { if(e.getSource() == startButton ) { greenButton.setIcon(greenBlink); buttonTimer.start(); greenButton.setIcon(greenReg); } } 

这是第一个保持简单的按钮的代码。

您似乎试图在自己的侦听器中重新启动Timer,这是您不应该做的事情。 了解该侦听器中的actionPerformed方法将在每500毫秒的代码中重复调用,并且不需要尝试“重新启动”计时器,因为它已经在运行。 而是在actionPerformed方法内部,你应该有代码来决定哪个按钮应该改变图标/状态,以及放入哪个图标。

例如,请考虑以下代码。 它假定有两个图标,一个名为greenIcon,一个名为darkGreenIcon,我想每200毫秒交换这些图标。 在我的Timer的actionPerformed中,我将通过调用按钮上的getIcon()来检查按钮中当前显示的图标。 如果它是一个greenIcon,我会通过setIcon(...)在按钮中放置一个darkGreenIcon,反之亦然,如果它是一个darkGreenIcon,我将放入一个greenIcon。 代码看起来像:

  @Override public void actionPerformed(ActionEvent e) { // get icon from button Icon icon = greenButton.getIcon(); // check if it's the green icon if (icon == greenIcon) { icon = darkGreenIcon; // if so, make it the dark green icon } else { icon = greenIcon; // if not, make it the green icon } greenButton.setIcon(icon); // stuff it back into the button } 

例如,一个可运行的程序:

 import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import javax.swing.*; @SuppressWarnings("serial") public class FlashingButton extends JPanel { private static final String START = "Start"; private static final String STOP = "Stop"; private static final int TIMER_DELAY = 200; // millisecond delay private static final int BI_WIDTH = 400; private Icon greenIcon; private Icon darkGreenIcon; private JButton greenButton = new JButton(); private JButton startButton = new JButton(new StartAction(START)); private Timer timer = new Timer(TIMER_DELAY, new TimerListener()); public FlashingButton() { greenIcon = createMyIcon(Color.GREEN); darkGreenIcon = createMyIcon(Color.GREEN.darker()); greenButton.setIcon(greenIcon); setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40)); setLayout(new BorderLayout(20, 20)); add(greenButton, BorderLayout.CENTER); add(startButton, BorderLayout.PAGE_END); } // Ignore this code. It simply is present to create image icons // without having to use an actual image. This way you can run this code without an image private Icon createMyIcon(Color color) { BufferedImage img = new BufferedImage(BI_WIDTH, BI_WIDTH, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(color); g2.fillOval(5, 5, BI_WIDTH - 10, BI_WIDTH - 10); g2.setStroke(new BasicStroke(10f)); g2.setColor(Color.LIGHT_GRAY); g2.drawOval(5, 5, BI_WIDTH - 10, BI_WIDTH - 10); g2.dispose(); return new ImageIcon(img); } private class TimerListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { // get icon from button Icon icon = greenButton.getIcon(); // check if it's the green icon if (icon == greenIcon) { icon = darkGreenIcon; // if so, make it the dark green icon } else { icon = greenIcon; // if not, make it the green icon } greenButton.setIcon(icon); // stuff it back into the button } } // this is my startButton's Action. // an Action is like an "ActionListener on steroids" private class StartAction extends AbstractAction { public StartAction(String name) { super(name); // the text that appears in the button putValue(MNEMONIC_KEY, (int) name.charAt(0)); // the alt-key mnemonic } @Override public void actionPerformed(ActionEvent e) { if (timer.isRunning()) { // if the timer is currently running timer.stop(); // stop the Timer greenButton.setIcon(greenIcon); // set the icon back to the defaut green icon putValue(NAME, START); // change the button's text to "Start" } else { // otherwise the Timer's not running timer.start(); // Start it putValue(NAME, STOP); // change this button's text to "Stop" } } } private static void createAndShowGui() { JFrame frame = new JFrame("Flashing Button"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new FlashingButton()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> createAndShowGui()); } }