SwingWorker,Thread.sleep()或javax.swing.timer?我需要“插入暂停”

时间:2013-04-30 05:05:35

标签: java swing user-interface

我正在开发记忆游戏,我想设置它,所以我点击第一个"card",然后第二个,如果它们不一样,第二张卡显示几秒钟然后它们返回到"non-flipped"位置。

我尝试使用SwingWorkerThread.sleepSwingTimer,但我无法使用它。使用Thread.sleep第二张卡不会"flip"如果它是重复的,它会等待睡眠时间并消失。如果它不匹配则等待“面朝下”并且在睡眠定时器之后第一张卡确实翻转。无论我放置Thread.sleep的位置如何,都会发生这种情况。

使用Swing Timer只会在我与卡片交互时“更改计时器”,所以我最终会在激活之前翻转8张卡片。

我对SwingWorker没有运气,我甚至不确定它是否适用于我正在寻找的东西。

这是我的代码:

    class ButtonListener implements ActionListener
    {

        public void actionPerformed(ActionEvent e) 
        {
            for(int index = 0; index < arraySize; index++)
            {

                if(button[index] == e.getSource())
                {
                    button[index].setText(String.valueOf(cards.get(index)));
                    button[index].setEnabled(false);

                    number[counter]=cards.get(index);

                    if (counter == 0)
                    {
                        counter++;
                    }
                    else if (counter == 1)
                    {   
                        if (number[0] == number[1])
                        {
                            for(int i = 0; i < arraySize; i++)
                            {
                                if(!button[i].isEnabled())
                                {
                                    button[i].setVisible(false);
                                }
                            }
                        }
                        else
                        {
                            for(int i = 0; i < arraySize; i++)
                            {
                                if(!button[i].isEnabled())
                                {
                                    button[i].setEnabled(true);
                                    button[i].setText("Card");
                                }
                            }
                        }

                        counter = 0;
                    }
                }
            }
        }
    }

基本上我需要的是这个代码在计数器== 1时执行,并且卡不匹配:

    button[index].setText(String.valueOf(cards.get(index)));
                    button[index].setEnabled(false);

然后暂停一段时间card is revealed,最后恢复将卡片恢复到正面朝下的位置。

这是我尝试使用Thread.sleep()

class ButtonListener implements ActionListener
    {

        public void actionPerformed(ActionEvent e) 
        {
            for(int index = 0; index < arraySize; index++)
            {

                if(button[index] == e.getSource())
                {
                    button[index].setText(String.valueOf(cards.get(index)));
                    button[index].setEnabled(false);

                    number[counter]=cards.get(index);

                    if (counter == 0)
                    {
                        counter++;
                    }
                    else if (counter == 1)
                    {   
                        if (number[0] == number[1])
                        {
                            for(int i = 0; i < arraySize; i++)
                            {
                                if(!button[i].isEnabled())
                                {
                                    button[i].setVisible(false);
                                }
                            }
                        }
                        else
                        {
                            try 
                            {
                                Thread.sleep(800);
                            } 
                            catch (InterruptedException e1) 
                            {
                                e1.printStackTrace();
                            }

                            for(int i = 0; i < arraySize; i++)
                            {
                                if(!button[i].isEnabled())
                                {
                                    button[i].setEnabled(true);
                                    button[i].setText("Card");
                                }
                            }
                        }

                        counter = 0;
                    }
                }
            }
        }
    }

提前感谢任何建议

1 个答案:

答案 0 :(得分:3)

使用javax.swing.Timer安排触发的未来事件。这将允许您安全地更改UI,因为计时器是在事件调度线程的上下文中触发的。

能够同时翻转多张卡片的问题更多地与你没有设置防止用户翻卡而使用定时器的状态有关。

以下示例基本上只允许每组翻转一张卡片。

在两组中都翻转了一张卡后,计时器就会启动。当它被触发时,卡被重置。

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;

public class FlipCards {

    public static void main(String[] args) {
        new FlipCards();
    }

    public FlipCards() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class Card extends JPanel {

        private BufferedImage image;
        private boolean flipped = false;

        private Dimension prefSize;

        public Card(BufferedImage image, Dimension prefSize) {
            setBorder(new LineBorder(Color.DARK_GRAY));
            this.image = image;
            this.prefSize = prefSize;
        }

        @Override
        public Dimension getPreferredSize() {
            return prefSize;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            LinearGradientPaint lgp = new LinearGradientPaint(
                    new Point(0, 0),
                    new Point(0, getHeight()),
                    new float[]{0f, 1f},
                    new Color[]{Color.WHITE, Color.GRAY});
            g2d.setPaint(lgp);
            g2d.fill(new Rectangle(0, 0, getWidth(), getHeight()));
            if (flipped && image != null) {
                int x = (getWidth() - image.getWidth()) / 2;
                int y = (getHeight() - image.getHeight()) / 2;
                g2d.drawImage(image, x, y, this);
            }
            g2d.dispose();
        }

        public void setFlipped(boolean flipped) {

            this.flipped = flipped;
            repaint();

        }
    }

    public class CardsPane extends JPanel {

        private Card flippedCard = null;

        public CardsPane(List<BufferedImage> images, Dimension prefSize) {
            setLayout(new GridBagLayout());
            MouseAdapter mouseHandler = new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (flippedCard == null) {
                        Card card = (Card) e.getComponent();
                        card.setFlipped(true);
                        flippedCard = card;
                        firePropertyChange("flippedCard", null, card);
                    }
                }
            };
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.insets = new Insets(4, 4, 4, 4);
            gbc.fill = GridBagConstraints.BOTH;
            gbc.weightx = 0.25f;
            for (BufferedImage img : images) {
                Card card = new Card(img, prefSize);
                card.addMouseListener(mouseHandler);
                add(card, gbc);
            }
        }

        public Card getFlippedCard() {
            return flippedCard;
        }

        public void reset() {
            if (flippedCard != null) {
                flippedCard.setFlipped(false);
                flippedCard = null;
            }
        }
    }

    public class TestPane extends JPanel {

        private CardsPane topCards;
        private CardsPane bottomCards;

        private Timer resetTimer;

        public TestPane() {

            resetTimer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    topCards.reset();
                    bottomCards.reset();
                }
            });
            resetTimer.setRepeats(false);
            resetTimer.setCoalesce(true);

            PropertyChangeListener propertyChangeHandler = new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    Card top = topCards.getFlippedCard();
                    Card bottom = bottomCards.getFlippedCard();
                    if (top != null && bottom != null) {
                        resetTimer.start();
                    }
                }
            };
            BufferedImage[] images = new BufferedImage[4];
            try {
                images[0] = ImageIO.read(new File("./Card01.png"));
                images[1] = ImageIO.read(new File("./Card02.jpg"));
                images[2] = ImageIO.read(new File("./Card03.jpg"));
                images[3] = ImageIO.read(new File("./Card04.png"));

                Dimension prefSize = getMaxBounds(images);

                List<BufferedImage> topImages = new ArrayList<>(Arrays.asList(images));
                Random rnd = new Random(System.currentTimeMillis());
                int rotate = (int) Math.round((rnd.nextFloat() * 200) - 50);
                Collections.rotate(topImages, rotate);
                topCards = new CardsPane(topImages, prefSize);
                topCards.addPropertyChangeListener("flippedCard", propertyChangeHandler);

                List<BufferedImage> botImages = new ArrayList<>(Arrays.asList(images));

                int botRotate = (int) Math.round((rnd.nextFloat() * 200) - 50);
                Collections.rotate(botImages, botRotate);
                bottomCards = new CardsPane(botImages, prefSize);
                bottomCards.addPropertyChangeListener("flippedCard", propertyChangeHandler);

                setLayout(new GridBagLayout());
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.insets = new Insets(4, 4, 4, 4);
                gbc.gridwidth = GridBagConstraints.REMAINDER;
                add(topCards, gbc);
                add(bottomCards, gbc);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        protected Dimension getMaxBounds(BufferedImage[] images) {
            int width = 0;
            int height = 0;

            for (BufferedImage img : images) {
                width = Math.max(width, img.getWidth());
                height = Math.max(height, img.getHeight());
            }

            return new Dimension(width, height);
        }
    }
}