Объединение repaint () с Thread.Sleep () - PullRequest
1 голос
/ 09 января 2012

То, что я пытаюсь сделать, довольно просто, я хочу показать шаги алгоритма на экране, поэтому я пытаюсь объединить 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;
        }
    }

Ответы [ 4 ]

4 голосов
/ 09 января 2012

Не спать в ветке рассылки событий;это приведет к зависанию графического интерфейса.Для анимации используйте полезный для EDT класс, например javax.swing.Timer.

1 голос
/ 09 января 2012

Несколько идей, которые могут сделать ваш код чище:

  1. В вашем классе SomePanel поместите код обхода в метод из конструктора. Конструкторы предназначены для инициализации полей.
  2. Сначала запустите ваш статический графический интерфейс, а затем создайте рабочий поток для обновления через предыдущий метод (это будет ваш маленький «движок»). В этой теме вы можете позвонить sleep.
  3. В вашем методе traverseVerticesRecoursive выполните только перерисовку в потоке пользовательского интерфейса и обновление статуса в рабочем потоке.

Главное изменение, которое вы должны сделать, это не блокировать поток GUI с помощью вызовов сна, как они сказали вам в первом ответе.

0 голосов
/ 29 декабря 2016

Парень, вы можете использовать новую тему, отличную от темы 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);
    }
}
0 голосов
/ 22 января 2013

Thread.sleep - это долгосрочное задание.Когда вы выполняете такую ​​задачу в EDT, она блокирует выполнение всех запросов на перерисовку.Все запросы на перерисовку, находящиеся на рассмотрении и отправленные во время фазы ожидания, ставятся в очередь для дальнейшей обработки.

В результате, когда EDT выходит из фазы sleep, он объединяет все такие запросы на перерисовку (если объединение выполняетсявключен, который является свойством по умолчанию) в один перекрас, который выполняется.Если объединение не включено, то все запросы в очереди выполняются последовательно без промежутка времени.В результате кажется, что пользовательский интерфейс не обновился.

Для исправления ситуации используйте timer, который периодически срабатывает через определенные промежутки времени.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...