将 repaint() 与 Thread.Sleep() 结合起来

发布于 2024-12-25 12:09:46 字数 3081 浏览 1 评论 0原文

我想做的事情非常简单,我想在屏幕上显示算法的步骤,因此为什么我尝试将 repaint() 与 sleep() 结合起来,但我做错了,如果有人足够了解,我会喜欢它首先解释一下这段代码有什么问题,其次,我该怎么做才能让它工作......

谢谢!

在夏天,这段代码的目的是绘制 10 个红色顶点,然后以 200 毫秒的间隔将它们一一涂黑。

这是代码:

public class Tester {

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

        private static void ShowGUIGraph() {
            JFrame f = new JFrame("something");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel p=new JPanel();
            p.setLayout(new BorderLayout());
            p.add(BorderLayout.CENTER,new SomePanel());
            f.add(p);
            f.setPreferredSize(new Dimension(800,600));
            f.pack();
            f.setVisible(true);
        }
}

public class SomePanel extends JPanel {
    private static final long serialVersionUID = 1L;
    LinkedList<Vertex> vertices=new LinkedList<Vertex>();
    public SomePanel () {
        for (int i=0;i<10;i++) {
            Vertex v=new Vertex(i);
            v.setLocation(20+30*i, 20+30*i);
            vertices.add(v);
        }
        traverseVerticesRecoursive(0);
        traverseVerticesNonRecoursive();
    }
    public void traverseVerticesRecoursive(int i) {
        if (i>=vertices.size()) return;
        vertices.get(i).setColor(Color.black);

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        repaint();
        traverseVerticesRecoursive(i+1);
    }
    public void traverseVerticesNonRecoursive() {
        for (int i=0;i<10;i++) {
            vertices.get(i).setColor(Color.red);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            repaint();
        }
    }
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i=0;i<vertices.size();i++) {
            vertices.get(i).paintVertex(g);
        }

    }
}
   public class Vertex {
        private int x,y,tag,r=20;
        private Color color=Color.red;
        Vertex (int i) {
            tag=i;
        }
        public void setLocation(int x0,int y0) {
            x=x0;
            y=y0;
        }
        public int getX() {
            return x;
        }
        public int getY() {
            return y;
        }

        public void setColor(Color c) {
            color=c;
        }
        public boolean colorIs(Color c) {
            return (color.equals(c));
        }

        public void paintVertex(Graphics g) {
            g.setColor(color);
            g.fillOval(x,y,r,r);
            g.setColor(Color.BLACK);
            g.drawOval(x,y,r,r);
            g.drawString(""+tag, x+r/2, y+r/2+4);
        }
        public int getR() {
            return r;
        }
    }

What im trying to do is pretty simple, I want to show the steps of an algorithm on the screen, hence why im trying to combine repaint() with sleep(), but I am doing it wrong, Id love it if someone knows enough about it to firstly explain whats wrong with this code, and secondly, what do i do to make it work...

thanks!

in summery, what this code was meant to do is paint 10 red vertices, then balcken em one by one in intervals of 200 milliseconds.

here's the code:

public class Tester {

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

        private static void ShowGUIGraph() {
            JFrame f = new JFrame("something");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            JPanel p=new JPanel();
            p.setLayout(new BorderLayout());
            p.add(BorderLayout.CENTER,new SomePanel());
            f.add(p);
            f.setPreferredSize(new Dimension(800,600));
            f.pack();
            f.setVisible(true);
        }
}

public class SomePanel extends JPanel {
    private static final long serialVersionUID = 1L;
    LinkedList<Vertex> vertices=new LinkedList<Vertex>();
    public SomePanel () {
        for (int i=0;i<10;i++) {
            Vertex v=new Vertex(i);
            v.setLocation(20+30*i, 20+30*i);
            vertices.add(v);
        }
        traverseVerticesRecoursive(0);
        traverseVerticesNonRecoursive();
    }
    public void traverseVerticesRecoursive(int i) {
        if (i>=vertices.size()) return;
        vertices.get(i).setColor(Color.black);

        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        repaint();
        traverseVerticesRecoursive(i+1);
    }
    public void traverseVerticesNonRecoursive() {
        for (int i=0;i<10;i++) {
            vertices.get(i).setColor(Color.red);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            repaint();
        }
    }
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        for (int i=0;i<vertices.size();i++) {
            vertices.get(i).paintVertex(g);
        }

    }
}
   public class Vertex {
        private int x,y,tag,r=20;
        private Color color=Color.red;
        Vertex (int i) {
            tag=i;
        }
        public void setLocation(int x0,int y0) {
            x=x0;
            y=y0;
        }
        public int getX() {
            return x;
        }
        public int getY() {
            return y;
        }

        public void setColor(Color c) {
            color=c;
        }
        public boolean colorIs(Color c) {
            return (color.equals(c));
        }

        public void paintVertex(Graphics g) {
            g.setColor(color);
            g.fillOval(x,y,r,r);
            g.setColor(Color.BLACK);
            g.drawOval(x,y,r,r);
            g.drawString(""+tag, x+r/2, y+r/2+4);
        }
        public int getR() {
            return r;
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

单身情人 2025-01-01 12:09:46

不要在事件派发线程中休眠;这将导致 GUI 冻结。对于动画,请使用 EDT 友好的实用程序类,例如 javax.swing.Timer

Do not sleep in the Event Dispatch Thread; this will cause the GUI to freeze. For animation, use an EDT-friendly utility class, such as javax.swing.Timer.

酒废 2025-01-01 12:09:46

一些可能使您的代码更简洁的想法:

  1. 在您的 SomePanel 类中,将遍历代码放在构造函数之外的方法中。构造函数用于初始化字段。
  2. 首先启动静态 GUI,然后生成一个工作线程以通过前面的方法进行更新(这将是您的小型“引擎”)。在此线程中,您可以调用sleep
  3. traverseVerticesRecoursive 方法中,仅在 UI 线程上进行重绘,并在工作线程上进行状态更新。

您应该做的主要修改是不要通过睡眠调用来阻止 GUI 线程,正如他们在第一个答案中告诉您的那样。

Just a few ideas that might make your code cleaner:

  1. In your SomePanel class, put the traversing code in a method out of the constructor. Constructors are intended for initializing fields.
  2. First launch your static GUI, then spawn a worker thread to do the updates via the previous method (this would be your small "engine"). In this thread is were you can call sleep.
  3. In your traverseVerticesRecoursive method, do only the repaint on the UI thread, and the status update on your worker thread.

Tha main modification you should do is not to block the GUI thread with sleep calls, as they have told you in the first answer.

初吻给了烟 2025-01-01 12:09:46

Thread.sleep 是一个长时间运行的任务。当您在 EDT 中运行此类任务时,它会阻止执行所有重绘请求。所有待处理的重绘请求和在睡眠阶段发送的重绘请求都会排队等待将来处理。

因此,当 EDT 退出睡眠阶段时,它会将所有此类重绘请求(如果启用了默认属性的合并)合并为一个要执行的重绘。如果未启用合并,则所有排队的请求都会串行执行,中间没有任何时间间隔。结果似乎 UI 没有更新。

要纠正这种情况,请使用计时器,该计时器会在特定时间间隔后定期触发。

Thread.sleep is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.

As a result when the EDT comes out of the sleep phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.

To correct the situation use a timer which triggers periodically after specific intervals of time.

咆哮 2025-01-01 12:09:46

伙计,你可以使用与 EDT 线程不同的新线程来制作动画。例如,

 void play() {
    Thread thread = new Thread() {
        @Override
        public void run() {
            game();
        }
    };
    thread.start();
}

void game() {
    for (; ; ) {
        switch (state) {
            case GameData.ANIMATING:
                // call some function as repaint() to update GUI
                break;
            case GameData.GAME_ENDED:
                return;
            default:
                break;
        }

        diffTime = System.currentTimeMillis() - beforeTime;
        sleepTime = delay - diffTime;
        sleepTime = (sleepTime < 0) ? 0 : sleepTime;
        Thread.sleep(sleepTime);
    }
}

Guy, you could use a new Thread differ with EDT thread to make an animation. For example,

 void play() {
    Thread thread = new Thread() {
        @Override
        public void run() {
            game();
        }
    };
    thread.start();
}

void game() {
    for (; ; ) {
        switch (state) {
            case GameData.ANIMATING:
                // call some function as repaint() to update GUI
                break;
            case GameData.GAME_ENDED:
                return;
            default:
                break;
        }

        diffTime = System.currentTimeMillis() - beforeTime;
        sleepTime = delay - diffTime;
        sleepTime = (sleepTime < 0) ? 0 : sleepTime;
        Thread.sleep(sleepTime);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文