1

Hello guys I am doing a thread to update a ball over JFrame so I repaint the screen... and then paint the ball update its position .. and then draw the screen again ... draw the ball and the same cycle ... here is the code

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();
}

but the problem is that I don't see the ball... the paint of the screen always overrides the ball and the ball is like down under the Jframe ..

mKorbel
  • 109,525
  • 20
  • 134
  • 319
I.el-sayed
  • 325
  • 1
  • 5
  • 18
  • What is the type of your b2 and ob variables? I'm thinking that the problem might be because you're calling SWING code outside of the EDT (Event Dispatch Thread). It's fine to call repaint outside the EDT (repaint is one of the few exceptions), but if b2 is a swing (or awt) component, it isn't fine to call its methods outside the EDT. – DisplayName Dec 08 '12 at 16:34
  • the b2 variable is an instance of public class Ball extends JApplet which is the ball itself .. the ob variable is a refernce of the jframe object .. I send it to the ball to detrmine the height and the width of the frame to avoid going out of the boundries .. U know what ... when I comment this line repaint(); the ball shows up but over the jframe and the jframe didn't get updated which is expected .. but once I add it .. the ball disappear ... !! – I.el-sayed Dec 08 '12 at 16:48
  • 1
    You should not handle GUI updating tasks outside the EDT – Extreme Coders Dec 08 '12 at 17:16
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Dec 08 '12 at 21:42

3 Answers3

6

If you want to have animations in Swing, the recommended class to use is the javax.swing.Timer . This class allows you to perform operations on the Event Dispatch Thread at regular intervals.

Community
  • 1
  • 1
Robin
  • 36,233
  • 5
  • 47
  • 99
2

Some General Rules

  • Swing is not thread safe, you should only ever update UI components from within the context of the Event Dispatching Thread.
  • You do not control the paint process, the repaint manager does. You can request updates to occur by calling repaint, but you should never call update and paint directly when trying to update the display.
  • The Graphics context used by the paint sub system is a shared resource and is not guaranteed to be the same between paint cycles, you should never maintain a reference to it. You should also not rely on the results from JComponent#getGraphics this method is capable of returning null.

An Example Solution

You have a number of options, depending on what you want to ultimately achieve.

You could use a SwingWorker, but given the fact that all your going to is enter an infinite loop and it would easier to use SwingUtilities#invokeLater then actually use the publish method, this approach would actually be more work.

You could also use a Thread, but you'd end up with the same problems as using a SwingWorker

The simpliset solution, for what you're presented, is actually a 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);
        }

    }

}

You can take a look at Swing Timer and Concurrency in Swing for more info

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

If you access GUI components outside the EDT (Event Dispatch Thread) then you might encounter strange problems, Contrary if you perform long running tasks in the EDT then also you will get problems.

Check this post for more info on GUI Threading in Java

Community
  • 1
  • 1
Extreme Coders
  • 3,441
  • 2
  • 39
  • 55
  • nop it is not working .. it is as if I am painting the ball but there is no repaint to the screen .... so I still see the trace of the ball in the screen .... like I see the places of the ball where it was... and they aren't deleted ... which not what I want .. – I.el-sayed Dec 08 '12 at 17:33
  • calling `Thread.sleep` on the EDT is not-done as it will block the whole UI. Use the `javax.swing.Timer` class if you want animations in Swing – Robin Dec 08 '12 at 17:35