1

私がやろうとしていることは非常に単純です。アルゴリズムのステップを画面に表示したいので、なぜ repaint() と sleep() を組み合わせようとしていますが、間違っています。誰かが十分に知っていれば、それが大好きです最初にこのコードの何が問題なのかを説明し、次に、それを機能させるために何をすべきか...

ありがとう!

要約すると、このコードは 10 個の赤い頂点をペイントし、200 ミリ秒間隔で 1 つずつ balcken することを意図していました。

コードは次のとおりです。

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 に答える 4

4

イベントディスパッチスレッドで眠らないでください。これにより、GUI がフリーズします。アニメーションの場合、 などの EDT に適したユーティリティ クラスを使用しjavax.swing.Timerます。

于 2012-01-09T16:49:28.517 に答える
1

コードをよりクリーンにする可能性のあるいくつかのアイデア:

  1. SomePanelクラスで、コンストラクターの外のメソッドにトラバースコードを配置します。コンストラクターは、フィールドを初期化することを目的としています。
  2. 最初に静的GUIを起動し、次にワーカースレッドを生成して、前の方法(これは小さな「エンジン」になります)を介して更新を実行します。このスレッドでは、を呼び出すことができますsleep
  3. このtraverseVerticesRecoursiveメソッドでは、UIスレッドで再描画のみを実行し、ワーカースレッドでステータスの更新を実行します。

あなたがしなければならない主な変更は、最初の答えであなたに言ったように、スリープ呼び出しでGUIスレッドをブロックしないことです。

于 2012-01-09T17:35:54.097 に答える
0

Thread.sleep長時間実行されるタスクです。EDT でこのようなタスクを実行すると、すべての再描画要求の実行がブロックされます。保留中であり、スリープ フェーズ中に送信されたすべての再描画要求は、将来の処理のためにキューに入れられます。

その結果、EDT がsleepフェーズを終了すると、そのようなすべての再描画要求 (デフォルトのプロパティである結合が有効になっている場合) を単一の再描画に結合し、実行されます。合体が有効になっていない場合、キューに入れられたすべてのリクエストは、時間間隔なしで連続して実行されます。その結果、UI が更新されなかったようです。

状況を修正するには、timer特定の時間間隔の後に定期的にトリガーする を使用します。

于 2013-01-22T15:26:46.963 に答える
0

男、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);
    }
}
于 2016-12-29T14:28:17.713 に答える