Thread.sleep() 和 GUI

Posted

技术标签:

【中文标题】Thread.sleep() 和 GUI【英文标题】:Thread.sleep() and GUI 【发布时间】:2017-03-26 19:37:01 【问题描述】:

我刚刚在论坛上搜索,但找不到任何对我有帮助的东西。我的问题如下:我正在尝试创建一个小游戏,在这个游戏中,你必须在你朋友的背上走才能赢,当其中一个达到此目标时,游戏结束。 这是我为解释我的问题而编写的一个简单代码

我的应用程序中有 3 个类(属于包代码):

主要

游戏

位置

我的应用程序中有 9 个 .png(属于 img 包):

0.png j1_0.png j1_1.png j1_2.png j1_3.png j2_0.png j2_1.png j2_2.png j2_3.png

两个包都在 src 根目录下

头等舱:

package code;

public class Main

    public static Game game;

    public static void main(String[] args)

        game = new Game(8, 8);

    


二等奖:

package code;

import javax.swing.JPanel;
import javax.swing.JLabel;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class Game extends JFrame

    private Position j1, j2;
    private JPanel panel;
    private JLabel[][] grid;
    private int largeur, hauteur;

    public Game(int hauteur, int largeur) // >= 2

        super("Rattrape l'autre");
        this.largeur = largeur;
        this.hauteur = hauteur;
        this.panel = new JPanel(new GridBagLayout());
        this.add(this.panel);
        this.grid = new JLabel[largeur][hauteur];
        int x1 = (int) (Math.random() * largeur), y1 = (int) (Math.random() * hauteur), x2, y2;
        do
            x2 = (int) (Math.random() * largeur);
            y2 = (int) (Math.random() * hauteur);
        while(x2 == x1 && y2 == y1);
        this.j1 = new Position(x1, y1, (int) (Math.random() * 4));
        this.j2 = new Position(x2, y2, (int) (Math.random() * 4));
        updatePanel();
        this.setResizable(false);
        this.pack();
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.setVisible(true);
        this.addKeyListener(new KeyListener()

            @Override
            public void keyPressed(KeyEvent e)

                boolean over = false;
                if(e.getKeyCode() == KeyEvent.VK_Z)
                    if(j1.getY() != 0 && !(j1.getY() == j2.getY() + 1 && j1.getX() == j2.getX()))
                        j1.goesUp();
                    else if(j2.getDirection() == 0 && j1.getY() == j2.getY() + 1 && j1.getX() == j2.getX())
                        over = true;
                    
                    j1.turnUp();
                else if(e.getKeyCode() == KeyEvent.VK_D)
                    if(j1.getX() != largeur - 1 && !(j1.getX() == j2.getX() - 1 && j1.getY() == j2.getY()))
                        j1.goesRight();
                    else if(j2.getDirection() == 1 && j1.getX() == j2.getX() - 1 && j1.getY() == j2.getY())
                        over = true;
                    
                    j1.turnRight();
                else if(e.getKeyCode() == KeyEvent.VK_S)
                    if(j1.getY() != hauteur - 1 && !(j1.getY() == j2.getY() - 1 && j1.getX() == j2.getX()))
                        j1.goesDown();
                    else if(j2.getDirection() == 2 && j1.getY() == j2.getY() - 1 && j1.getX() == j2.getX())
                        over = true;
                    
                    j1.turnDown();
                else if(e.getKeyCode() == KeyEvent.VK_Q)
                    if(j1.getX() != 0 && !(j1.getX() == j2.getX() + 1 && j1.getY() == j2.getY()))
                        j1.goesLeft();
                    else if(j2.getDirection() == 3 && j1.getX() == j2.getX() + 1 && j1.getY() == j2.getY())
                        over = true;
                    
                    j1.turnLeft();
                
                if(e.getKeyCode() == KeyEvent.VK_UP)
                    if(j2.getY() != 0 && !(j2.getY() == j1.getY() + 1 && j2.getX() == j1.getX()))
                        j2.goesUp();
                    else if(j1.getDirection() == 0 && j2.getY() == j1.getY() + 1 && j2.getX() == j1.getX())
                        over = true;
                    
                    j2.turnUp();
                else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
                    if(j2.getX() != largeur - 1 && !(j2.getX() == j1.getX() - 1 && j2.getY() == j1.getY()))
                        j2.goesRight();
                    else if(j1.getDirection() == 1 && j2.getX() == j1.getX() - 1 && j2.getY() == j1.getY())
                        over = true;
                    
                    j2.turnRight();
                else if(e.getKeyCode() == KeyEvent.VK_DOWN)
                    if(j2.getY() != hauteur - 1 && !(j2.getY() == j1.getY() - 1 && j2.getX() == j1.getX()))
                        j2.goesDown();
                    else if(j1.getDirection() == 2 && j2.getY() == j1.getY() - 1 && j2.getX() == j1.getX())
                        over = true;
                    
                    j2.turnDown();
                else if(e.getKeyCode() == KeyEvent.VK_LEFT)
                    if(j2.getX() != 0 && !(j2.getX() == j1.getX() + 1 && j2.getY() == j1.getY()))
                        j2.goesLeft();
                    else if(j1.getDirection() == 3 && j2.getX() == j1.getX() + 1 && j2.getY() == j1.getY())
                        over = true;
                    
                    j2.turnLeft();
                
                updatePanel();
                if(over)
                    end();
                

            

            @Override
            public void keyReleased(KeyEvent e)

            @Override
            public void keyTyped(KeyEvent e)

        );

    

    public void updatePanel()

        GridBagConstraints c = new GridBagConstraints();
        this.panel.removeAll();
        for(int x = 0; x < largeur; x++)
            for(int y = 0; y < hauteur; y++)
                if(x == j1.getX() && y == j1.getY())
                    this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/j1_" + j1.getDirection() + ".png")));
                else if(x == j2.getX() && y == j2.getY())
                    this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/j2_" + j2.getDirection() + ".png")));
                else
                    this.grid[x][y] = new JLabel(new ImageIcon(Main.class.getResource("/img/0.png")));
                
                c.gridx = x;
                c.gridy = y;
                this.panel.add(this.grid[x][y], c);
            
        
        this.panel.revalidate();

    

    public void end()

        try
            Thread.sleep(1000);
        catch(InterruptedException e)
        Main.game.dispose();


    


三等:

package code;

public class Position

    private int x, y, direction;

    public Position(int x, int y, int direction)

        this.x = x;
        this.y = y;
        this.direction = direction;

    

    public int getX()

        return this.x;

    

    public int getY()

        return this.y;

    

    public int getDirection()

        return this.direction;

    

    public void goesUp()

        this.y--;

    

    public void goesRight()

        this.x++;

    

    public void goesDown()

        this.y++;

    

    public void goesLeft()

        this.x--;

    

    public void turnUp()

        this.direction = 0;

    

    public void turnRight()

        this.direction = 1;

    

    public void turnDown()

        this.direction = 2;

    

    public void turnLeft()

        this.direction = 3;

    


最后,我的问题是这个:

我想要这样,例如,当玩家 1 向左看并且他就在玩家 2 的顶部,而玩家 2 向下看时,如果玩家 1 向下移动,它应该赢得游戏,但在显示玩家 1 往下看。

我尝试了很多输入 o 测试,它似乎可以工作,因为当 over 设置为 true 时,程序会进入 updatePanel(),然后它会启动 end(),它应该休眠 1 秒,然后处理frame.. 但它没有,它确实在最后启动了 updatePanel(),它更新了 j1 的值(作为前面的算法,我的意思是根据键盘输入分配值的算法,让他低头)但它不显示新网格,所以我迷路了:p

感谢您的建议,希望您能解决问题,而且算法很简单,而且不会那么长,所以你们应该不难理解它:)

【问题讨论】:

你写道:加上算法很简单,而且不长,所以应该不难理解。错误,错误的评估:您在那里放置了相当多的代码,带有 longy longy if /else 链,以及带有 if ... 的嵌套循环和大量局部变量。这样的代码难以阅读。这需要相当的努力来消化它,然后弄清楚你需要帮助的究竟是什么问题。你看,这里不是“我们为你调试整个程序”的服务。也许其他人有更多的时间/动机,但如果只有 投下反对票。 plus the algorithm is easy - 算法无关紧要。执行 updatePanel() 方法时会出现问题。因此,当您在论坛上发布问题时,您会发布演示问题的代码。所以你需要隔离问题。在这种情况下,您的所有 KeyListener 逻辑都可以通过简单地调用“updatePanel()”方法来替换。换句话说,忘记玩游戏,而只是测试游戏结束时会发生什么。这称为SSCCE。每个问题都使用SSCCE,而不是代码的核心转储。 【参考方案1】:

应该休眠 1 秒,然后处理框架..

您不能在Event Dispatch Thread(EDT) 上使用Thread.sleep()。这将导致 GUI 休眠,这意味着它不会被重新绘制。

相反,您需要使用单独的线程,可能是 SwingWorker。 SwingWorker 将允许您使用 Thread.sleep(),然后您可以在完成睡眠后发布结果。

阅读 Concurrency 上的 Swing 教程部分,了解更多信息和示例。

【讨论】:

以上是关于Thread.sleep() 和 GUI的主要内容,如果未能解决你的问题,请参考以下文章

C#中的Task.Delay()和Thread.Sleep()区别

Thread.sleep() 实现

多线程编程里的thread.sleep问题

使用 boost::this_thread::sleep_for() 和常规 sleep() 函数有啥区别?

kernel32.dll Sleep 和 Thread.Sleep() 之间的任何区别

Thread.sleep() 和 Thread.yield() 区别