Simon 说的闪烁按钮
Blinking Button for Simon Says
我正在制作一个 Simon says 程序,我需要按钮在生成随机模式时闪烁,以便用户知道输入什么。我的问题是我无法让我的按钮(JButtons 是图像)闪烁,我的逻辑是有两个按钮彼此重叠,一个可见,一个不可见,然后切换按钮可见性,等待一秒钟,然后将其改回.我试过使用 Thread.sleep()、wait() 甚至繁忙的循环来等待,但 none 已经奏效了。有人告诉我,摇摆计时器是我最好的选择,而这正是我想要使用的。另外,我希望按钮在单击开始按钮后开始闪烁。
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);
}
}
为了保持简单,这只是第一个按钮的代码。
您似乎试图在其自己的侦听器中重新启动计时器,这是您不应该做的事情。了解该侦听器中的 actionPerformed 方法将在您的代码中每 500 毫秒重复调用一次,并且无需尝试 "re-start" 计时器,因为它已经 运行。在 actionPerformed 方法内部,您应该有代码来决定哪个按钮应该更改图标/状态,以及要将哪个图标放入其中。
例如,考虑下面的代码。它假设有两个图标,一个叫 greenIcon,一个叫 darkGreenIcon,我想每 200 毫秒交换一次这些图标。在我的计时器的 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());
}
}
我正在制作一个 Simon says 程序,我需要按钮在生成随机模式时闪烁,以便用户知道输入什么。我的问题是我无法让我的按钮(JButtons 是图像)闪烁,我的逻辑是有两个按钮彼此重叠,一个可见,一个不可见,然后切换按钮可见性,等待一秒钟,然后将其改回.我试过使用 Thread.sleep()、wait() 甚至繁忙的循环来等待,但 none 已经奏效了。有人告诉我,摇摆计时器是我最好的选择,而这正是我想要使用的。另外,我希望按钮在单击开始按钮后开始闪烁。
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);
}
}
为了保持简单,这只是第一个按钮的代码。
您似乎试图在其自己的侦听器中重新启动计时器,这是您不应该做的事情。了解该侦听器中的 actionPerformed 方法将在您的代码中每 500 毫秒重复调用一次,并且无需尝试 "re-start" 计时器,因为它已经 运行。在 actionPerformed 方法内部,您应该有代码来决定哪个按钮应该更改图标/状态,以及要将哪个图标放入其中。
例如,考虑下面的代码。它假设有两个图标,一个叫 greenIcon,一个叫 darkGreenIcon,我想每 200 毫秒交换一次这些图标。在我的计时器的 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());
}
}