SwingWorker、Thread.sleep() 还是 javax.swing.timer?我需要“插入一个暂停" [英] SwingWorker, Thread.sleep(), or javax.swing.timer? I need to "insert a pause"

查看:23
本文介绍了SwingWorker、Thread.sleep() 还是 javax.swing.timer?我需要“插入一个暂停"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个记忆游戏,我想设置它,所以我点击第一个 "card",然后点击第二个,如果它们不一样,第二个卡片会显示一个几秒钟,然后他们返回到 非翻转" 位置.

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.

我尝试使用 SwingWorkerThread.sleepSwingTimer 但我无法让它工作.使用 Thread.sleep 第二张卡片不会 "flip" 如果它是重复的,它会等待睡眠时间并消失.如果它不匹配,它等待面朝下",并且在睡眠计时器之后第一张卡确实翻转回来.无论我将 Thread.sleep 放在哪里,都会发生这种情况.

I tried using SwingWorker, Thread.sleep and SwingTimer but I cant get it to work. With Thread.sleep the second card wont "flip" if it's a duplicate it waits the amount of sleep time and disappears. 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.

使用 Swing Timer 时,它似乎只会在我与卡片交互时更改计时器",因此我最终在它激活之前翻转了 8 张卡片.

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.

我对 SwingWorker 不走运,我什至不确定它是否适用于我正在寻找的东西.

I've had no luck with SwingWorker and I'm not even sure it will work for what I'm looking for.

这是我的代码:

    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 并且卡片不匹配时执行此代码:

Basically what I need is for this code to execute when the counter == 1, and the card is not a match:

    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.

这是我用 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;
                    }
                }
            }
        }
    }

提前感谢您的建议

推荐答案

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

Use javax.swing.Timer to schedule a future event to trigger. This will allow you to make changes to the UI safely, as the timer is triggered within the context of the Event Dispatching Thread.

能够同时翻转多张卡片的问题更多是因为您没有设置阻止用户翻转卡片的状态然后使用计时器.

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

这篇关于SwingWorker、Thread.sleep() 还是 javax.swing.timer?我需要“插入一个暂停"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆