1

こんにちは皆さん、私はJFrameを介してボールを更新するスレッドを実行しているので、画面を再描画します...そしてボールをペイントしてその位置を更新します..次に画面を再度描画します...ボールと同じサイクルを描画します...ここにコードがあります

private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
   Thread t = new Thread()
   {
     public void run()
     {
         while(true)
         {
             repaint();
             b2.update(ob,2);
             b2.paint(ob.getGraphics());

             b2.setT(b2.getT() + 1);
             try {
                 Thread.sleep(50);
             } catch (InterruptedException ex) {
                 System.out.println("Error in Sleeping");
             }

         }
     }
   };

   t.start();
}

しかし問題は、ボールが見えないことです...画面のペイントは常にボールを上書きし、ボールはJframeの下のようです..

4

3 に答える 3

6

Swing でアニメーションを使用する場合、推奨されるクラスはjavax.swing.Timer. このクラスを使用すると、定期的にイベント ディスパッチ スレッドで操作を実行できます。

于 2012-12-08T17:39:52.333 に答える
2

いくつかの一般規則

  • Swing はスレッド セーフではありません。イベント ディスパッチ スレッドのコンテキスト内からのみ UI コンポーネントを更新する必要があります。
  • ペイント プロセスはユーザーが制御するのではなく、再ペイント マネージャーが制御します。を呼び出して更新を要求することはできますが、表示を更新しようとするときに直接andをrepaint呼び出さないでください。updatepaint
  • ペイント サブシステムによって使用されるGraphicsコンテキストは共有リソースであり、ペイント サイクル間で同じであることが保証されていないため、参照を保持しないでください。JComponent#getGraphicsまた、このメソッドの結果が null を返すことに依存しないでください。

ソリューション例

最終的に何を達成したいかによって、いくつかのオプションがあります。

を使用することもできますがSwingWorker、無限ループに入ることがすべてであり、SwingUtilities#invokeLater実際にpublishメソッドを使用するよりも使いやすいという事実を考えると、このアプローチは実際にはより多くの作業になります。

を使用することもできますが、を使用しThreadた場合と同じ問題が発生します。SwingWorker

あなたが提示したものに対する単純化された解決策は、実際にはjavax.swing.Timer

public class Blinky {

    public static void main(String[] args) {
        new Blinky();
    }

    public Blinky() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new BlinkyPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    protected class BlinkyPane extends JPanel {

        private JLabel blinkyLabel;
        private boolean blink = false;

        public BlinkyPane() {
            setLayout(new GridBagLayout());
            blinkyLabel = new JLabel("I'm blinking here");
            blinkyLabel.setBackground(Color.RED);
            add(blinkyLabel);

            Timer timer = new Timer(250, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    blink = !blink;
                    if (blink) {
                        blinkyLabel.setForeground(Color.YELLOW);
                    } else {
                        blinkyLabel.setForeground(Color.BLACK);
                    }
                    blinkyLabel.setOpaque(blink);
                    repaint();
                }
            });
            timer.setRepeats(true);
            timer.setCoalesce(true);
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 100);
        }

    }

}

詳細については、Swing のSwing TimerConcurrency を参照してください。

于 2012-12-08T20:26:54.413 に答える
0

EDT (イベント ディスパッチ スレッド) の外部で GUI コンポーネントにアクセスすると、おかしな問題が発生する可能性があります。逆に、EDT で長時間実行されるタスクを実行すると、問題が発生します。

詳細については、この投稿を確認してくださいGUI Threading in Java

于 2012-12-08T17:23:36.623 に答える