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
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.
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
Some General Rules
repaint
, but you should never call update
and paint
directly when trying to update the display.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