在JFrame Java中闪烁

时间:2012-12-08 16:29:25

标签: java swing concurrency java-2d

大家好,我正在做一个线程来更新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下面......

3 个答案:

答案 0 :(得分:6)

如果您想在Swing中使用动画,建议使用的类是javax.swing.Timer。此类允许您定期对事件调度线程执行操作。

答案 1 :(得分:2)

一些一般规则

  • Swing不是线程安全的,您应该只在事件调度线程的上下文中更新UI组件。
  • 您不会控制绘制过程,重绘经理会这样做。您可以致电repaint请求更新,但在尝试更新显示时,切勿直接致电updatepaint
  • paint子系统使用的Graphics上下文是一个共享资源,不保证在绘制周期之间是相同的,你永远不应该保持对它的引用。您也不应该依赖JComponent#getGraphics的结果,此方法能够返回null。

示例解决方案

您有多种选择,具体取决于您最终要达到的目标。

您可以使用SwingWorker,但考虑到您所有进入无限循环的事实并且更容易使用SwingUtilities#invokeLater然后实际使用publish方法,方法实际上会更多的工作。

您也可以使用Thread,但最终会遇到与使用SwingWorker

相同的问题

对于您所呈现的内容,simpliset解决方案实际上是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 TimerConcurrency in Swing了解详情

答案 2 :(得分:0)

如果您访问EDT(事件调度线程)之外的GUI组件,那么您可能会遇到奇怪的问题,如果您在EDT中执行长时间运行的任务,那么您也会遇到问题。

查看this帖子,了解有关GUI Threading in Java

的更多信息