简体   繁体   English

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

[英]SwingWorker, Thread.sleep(), or javax.swing.timer? I need to “insert a pause”

I'm working on a memory game and I want to set it up so I click the first "card" , then the second and if they are not the same the second card shows for a few seconds then they return to the "non-flipped" position. 我正在做一个记忆游戏,所以我想设置它,所以我单击第一个"card" ,然后单击第二个卡片;如果它们不相同,则第二个卡片显示几秒钟,然后它们返回"non-flipped"卡片。 "non-flipped"位置。

I tried using SwingWorker , Thread.sleep and SwingTimer but I cant get it to work. 我尝试使用SwingWorkerThread.sleepSwingTimer但无法正常工作。 With Thread.sleep the second card wont "flip" if it's a duplicate it waits the amount of sleep time and disappears. 使用Thread.sleep ,如果第二张卡重复,则第二张卡不会"flip" ,它会等待一段时间的睡眠时间并消失。 If its not a match it waits "face down" and after the sleep timer the first card does flip back. 如果不匹配,它将等待“面朝下”,并且在睡眠计时器之后,第一张卡确实会向后翻转。 This happens regardless of where I place the Thread.sleep. 无论我将Thread.sleep放在哪里,都会发生这种情况。

With Swing Timer it only appears to "change the timer" while I'm interacting with the cards so I end up flipping 8 cards before it activates. 使用Swing Timer ,当我与卡片互动时,它似乎只是“更改计时器”,因此最终在激活之前翻转了8张卡片。

I've had no luck with SwingWorker and I'm not even sure it will work for what I'm looking for. 我在SwingWorker运气不好,甚至不确定它是否SwingWorker我的需求。

This is the code I have: 这是我的代码:

    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;
                    }
                }
            }
        }
    }

Basically what I need is for this code to execute when the counter == 1, and the card is not a match: 基本上,我需要的是在计数器== 1且卡不匹配时执行此代码:

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

Then a pause so the card is revealed for that time, and finally it resumes to returning the card to its face down position. 然后暂停片刻,以使card is revealed在该时间card is revealed ,最后恢复到将卡放回其正面朝下的位置。

This is what I tried with Thread.sleep() : 这是我用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;
                    }
                }
            }
        }
    }

Thanks in advance for any advice 预先感谢您的任何建议

Use javax.swing.Timer to schedule a future event to trigger. 使用javax.swing.Timer安排将来的事件来触发。 This will allow you to make changes to the UI safely, as the timer is triggered within the context of the Event Dispatching Thread. 这将允许您安全地对UI进行更改,因为计时器是在事件调度线程的上下文中触发的。

The problem with been able to flip multiple cards simultaneously has more to do with you not setting up a state that prevents the user from flipping cards then the use of timers. 能够同时翻转多张卡片的问题更多与您没有设置阻止用户翻转卡片的状态而不是使用计时器有关。

The following example basically only allows one card to be flipped per group at a time. 以下示例基本上只允许每组一次翻转一张卡。

Once a card has been flipped in both groups, the timer is started. 一旦在两个组中都翻转了卡,就启动计时器。 When it is triggered, the cards are reset. 触发后,卡将重置。

在此处输入图片说明

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);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM