【问题标题】:swing timer doesn't work properly [closed]摆动计时器无法正常工作[关闭]
【发布时间】:2011-10-28 18:40:30
【问题描述】:

您好,我正在开发一个项目(java 记忆游戏),首先我想了解摇摆计时器的工作原理。首先,我的主类实现了ActionListenerItemListener。我在actionPerformed(ActionEvent e) 中使用计时器,如果用户选择了不同图片的两张卡,那么我使用timer.start() 给他几秒钟的时间查看图片,然后它们将再次关闭。但是如果用户选择了两张不同的图片,他们会突然关闭,所以我看不到第二张图片。我阅读了一些关于摇摆计时器的教程,但我想我理解错了。顺便说一下,我创建了我的 SSCCE,如果你能帮助我,我将不胜感激。无论如何谢谢...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Menu;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.Random;

import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.border.*;

public class ConcentrationGame4 extends JFrame implements ActionListener, ItemListener{

    private static final long serialVersionUID = 1L;
    private int buttoncounter=0;
    private int counter = 0;
    private JFrame frame;
    private JPanel mainPanel;
    private JPanel buttonPanel;
    private JMenuBar menuBar;
    private JMenu menu;
    private JMenuItem menuItem;
    private int[] arr = new int[16];
    private int i,j;
    private int random;
    private int size = 4;
    private Icon hidden;
    private GameButton buttonFirst;
    private GameButton buttonSecond;
    private Timer timer;

    private Icon img[] = {UIManager.getIcon("OptionPane.errorIcon"),
            UIManager.getIcon("OptionPane.informationIcon"),
            UIManager.getIcon("OptionPane.warningIcon")};

    private Icon iconList[] = new ImageIcon[size];

    public ConcentrationGame4(){
        createArray();
        initComponents();
    }


    private void initComponents(){

        frame = new JFrame("Concentration Game");
        menuBar = new JMenuBar();
        menu = new JMenu("Menu");
        frame.setJMenuBar(menuBar);
        menuBar.add(menu);
        menuItem = new JMenuItem("New Game");
        menu.add(menuItem);
        menuItem = new JMenuItem("Solve");
        menu.add(menuItem);
        menuItem = new JMenuItem("Exit");
        menu.add(menuItem);
        mainPanel = new JPanel(new BorderLayout(5, 5));
        mainPanel.setBorder(new EmptyBorder(4,4,4,4));
        frame.setContentPane(mainPanel);
        buttonPanel = new JPanel(new GridLayout(4,4,5,5));
        buttonPanel.setBackground(Color.green);

        timer = new Timer(2000,this);

        for(i=0; i<4; i++){

            final GameButton button = new GameButton(iconList[i]);
            button.addItemListener(this);
            button.addActionListener(this);
            buttonPanel.add(button);

        }

        mainPanel.add(buttonPanel, BorderLayout.CENTER);
        frame.setSize(300, 300);
        //frame.pack();
        frame.setLocation(300, 300);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    public void itemStateChanged(ItemEvent e){

        GameButton button = (GameButton) e.getItem();

        button.setState();
    }

    public void actionPerformed(ActionEvent e){
        GameButton button = (GameButton) e.getSource();

        if(button.isSelected()){
            buttoncounter++;

            if(buttoncounter==1){
                buttonFirst = (GameButton) e.getSource();
            }
            else if(buttoncounter==2){

                buttonSecond = (GameButton) e.getSource();
                buttoncounter=0;

                    if( checkPairs(buttonFirst,buttonSecond) ) {
                        retirePair(buttonFirst,buttonSecond);
                    }

                    else{   
                        timer.start();
                        falsePair(buttonFirst, buttonSecond);

                    }

            }

    }

    }

    class GameButton extends JToggleButton{

        private static final long serialVersionUID = 1L;
        private Icon icon;

        public GameButton(Icon icon){
            this.icon = icon;
        }

         public void setState() {
                if (this.isSelected() || !this.isEnabled()) {
                    this.setIcon(icon);
                }

                else {
                    this.setIcon(hidden);
                }
            }
        }

    private void retirePair(GameButton a, GameButton b){

        a.setSelected(true);
        a.setEnabled(false);
        b.setSelected(true);
        b.setEnabled(false);

    }

    private void falsePair(GameButton buttonFirst, GameButton buttonSecond){

        buttonFirst.setIcon(hidden);
        buttonFirst.setSelected(false);
        buttonSecond.setIcon(hidden);
        buttonSecond.setSelected(false);
    }

    private boolean checkPairs(GameButton first, GameButton second){
        if(first.getIcon().equals(second.getIcon()))
            return true;
        else
            return false;
    }

    private void createArray(){
        Random rnd = new Random();
        while(i<4){

            random = rnd.nextInt(3)+1;
            if(!includes(random)){
                arr[i]=random;
                iconList[i] = img[random-1];
                i++;
            }
        }
    }

    public boolean includes(int rnd){
        counter=0;
        for(j=0; j<arr.length; j++){

            if(arr[j] == rnd){
                counter++;
                if(counter>1)
                    return true;
            }
        }

        return false;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        new ConcentrationGame4();

    }

}

【问题讨论】:

  • 再一次,根据人们在stackoverflow.com/q/7910639/1005662 中的反应,这不是 sscce。这是代码转储和帮助请求。请了解什么是 sscce:sscce.org 另外,这几乎是上述 stackoverflow 链接的副本...
  • 是的,但我删除了程序中一些不必要的部分。我的意思是我没有使用我自己的图标,也没有创建很多按钮(至少 4 个才能理解它),所以它很容易复制和编译给其他人。我的意思是我看不到更多不必要的代码。那你对我有什么期望?一般来说,我会创建 20 个按钮,它们有自己的图标 blablabla。是的,这个主题与旧主题非常相似。但如果你仔细阅读并查看代码,我做了一些更改,只是想知道计时器是如何工作的......
  • 它不短,但至少是自包含和可编译的。
  • 我不明白为什么人们降低利率_?之前问过几乎相同的问题的原因是什么?
  • Swing Timer 实际上工作正常——也就是说,它只做你告诉它做的事情。您的代码有错误,但我认为 JB Nizet 已经发现了问题并为此提供了解决方案 (1+)。

标签: java swing user-interface timer


【解决方案1】:

使用 Swing Timer 暂停动作 xxx 秒的示例:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class QuickTimerEg extends JPanel {
   private static final int TIMER_DELAY = 2000;
   private boolean buttonsWorking = true;
   private JButton btn1 = null;
   private JButton btn2 = null;
   private Timer swingTimer;

   public QuickTimerEg() {
      ActionListener btnListener = new ActionListener() {
         public void actionPerformed(ActionEvent e) {
            btnActionPerformed(e);
         }
      };
      setLayout(new GridLayout(4, 4));
      for (int i = 0; i < 4; i++) {
         for (int j = 0; j < 4; j++) {
            JButton button = new JButton("   ");
            button.addActionListener(btnListener);
            add(button);
         }
      }
   }

   private void btnActionPerformed(ActionEvent e) {
      if (!buttonsWorking) {
         return;
      }
      JButton button = (JButton)e.getSource();
      button.setBackground(Color.blue);
      button.setEnabled(false);
      if (btn1 == null) {
         btn1 = button;
      } else {
         buttonsWorking = false;
         btn2 = button;
         swingTimer = new Timer(TIMER_DELAY, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               btn1.setBackground(null);
               btn2.setBackground(null);
               btn1.setEnabled(true);
               btn2.setEnabled(true);
               btn1 = null;
               btn2 = null;
               buttonsWorking = true;               
            }
         });
         swingTimer.setRepeats(false);
         swingTimer.start();
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("QuickTimerEg");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new QuickTimerEg());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

【讨论】:

  • 我注意到我必须完全尝试理解 actionevents,因为我不知道我们可以在 actionPerformed 中使用 actionlistener。所以事情是当一个事件被触发时,一个动作监听器将处理它,那么内部动作监听器呢。它处理相同的event_吗? (非常感谢您的帮助,因为我在这件事上被困了好几天,现在看起来更清楚了)
  • 如此简单,就像 Swing +1 一样
【解决方案2】:

我不知道你想做什么,但你将this 作为参数传递给 Timer 构造函数。这意味着每隔 2 秒,将调用 this(ConcentrationGame4 的实例)的 actionPerformed 方法。这个方法做的第一件事是

GameButton button = (GameButton) e.getSource();

显然,这会引发异常,因为事件的来源不是游戏按钮,而是计时器。

要了解 Timer 的作用及其工作原理,非常简单。你只需要阅读它的 api 文档:http://download.oracle.com/javase/6/docs/api/javax/swing/Timer.html。该文档甚至会引导您进入一个解释它们如何工作的教程,并附有示例。

【讨论】:

  • 我只是想,如果我在falsePair() 方法下面使用timer.start(),它会停止2 秒,然后它会继续工作
  • 不,这不是定时器的作用。阅读 f** 文档。 Thread.sleep 会这样做,但如果你在事件调度线程中这样做,GUI 将冻结 2 秒。
  • 好吧,我承认这是一个愚蠢的帖子,所以我要删除它。对不起让你生气了:)
  • 你没有让我生气。我在这里回答的问题有一半可以通过阅读文档来回答。我只是希望你学到了一些东西,并且你现在会养成阅读文档的习惯。
  • 不要删除这个帖子或线程,因为它至少不是愚蠢的。在这里,我不同意 JB Nizet 的观点,因为 Swing Timer 可以为此工作,而事实上我已经编写了这样的代码。让它不再重复。
【解决方案3】:

顺便说一句,您可能想看看使用List&lt;Icon&gt;List&lt;GameButton&gt;。这样的Collections 很容易以可靠的方式洗牌。另外,请注意单个 GameButton 和它们的集合之间的区别,在 GameButton 类之外。当任何一个按钮被点击时,您都需要检查集合

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.Timer;
import javax.swing.UIManager;

/** @see http://stackoverflow.com/questions/7933424 */
public class ButtonTimer extends JPanel {

    private List<Icon> list = new ArrayList<Icon>();
    private List<GameButton> buttons = new ArrayList<GameButton>();
    private Timer timer = new Timer(1000, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            createPanel();
        }
    });

    public ButtonTimer() {
        this.setLayout(new GridLayout(1, 0));
        list.add(UIManager.getIcon("OptionPane.errorIcon"));
        list.add(UIManager.getIcon("OptionPane.informationIcon"));
        list.add(UIManager.getIcon("OptionPane.warningIcon"));
        list.add(UIManager.getIcon("OptionPane.questionIcon"));
        createPanel();
        timer.start();
    }

    private void createPanel() {
        Collections.shuffle(list);
        this.removeAll();
        for (Icon icon : list) {
            GameButton gb = new GameButton(icon);
            buttons.add(gb);
            this.add(gb);
        }
        this.revalidate();
    }

    class GameButton extends JToggleButton {

        private Icon icon;

        public GameButton(Icon icon) {
            super(icon);
            this.icon = icon;
        }
    }

    private void display() {
        JFrame f = new JFrame("ButtonTimer");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ButtonTimer().display();
            }
        });
    }
}

【讨论】:

  • 感谢这对我来说是一个很好的例子
  • 优秀。不要太气馁;很明显,您正在努力采纳您收到的建议。提问时,让您的示例专注于问题的特定方面,例如@Hovercraft 对Timer 的使用和我对shuffle() 的使用。构建这样一个示例需要做更多的工作,但这些努力对您来说是有价值的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-15
  • 1970-01-01
相关资源
最近更新 更多