Threading a paint method - java

I was wondering how I would thread the following code, or just a method in general:
public void run (){
public void paint(Graphics g) {
g.fillRect(20, 20, 20, 20);
for (int i = 20; i < 1000; i++) {
g.fillRect(20, i, 20, 20);
Thread.sleep(10);
}
}
}
I find that I am unable to make a thread of this code because I get an illegal start of expression error, which is fair but I do not see a way around it.

Its hard to tell what you are doing,
but seems like you are trying to override paint() of a Runnable from within its run() method.
This can surely not be done.
The logic is
Take a component
Override its paint method to draw what we need
Call method to update co-ordinates of rectangle (or in this case timer will do that)
Than call repaint() on the component so paint method may be called again and redraw the rectangle with its new co-ordinates (Timer would also take care of repainting after changing co-ordinates of Rectangle)
repeat last 2 steps as many times as needed/wanted
(when I say component I actually mean JPanel, paint method refers to overridden paintComponent(..) of JPanel as this is best practice.)
Some suggestions:
1) Dont override paint rather use JPanel and override paintComponent.
2) Dont forget to honor the paint chain and call super.XXX implementation of overridden paintComponent(Graphics g) (or any overridden method for that fact) unless purposefully leaving it out. i.e
class MyPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//do drawings here
}
}
3) If drawing in paintComponent it is usually needed to override getPreferredSize() and return Dimensions which fit the contents/drawings of JPanel, i.e:
class MyPanel extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(300,300);
}
}
3) Look at Swing Timer instead of Thread.sleep(..) as sleep will block GUI thread and make it seem to be frozen. i.e
Timer t = new Timer(10, new AbstractAction() {
int count = 20;
#Override
public void actionPerformed(ActionEvent ae) {
if (count < 1000) {
//increment rectangles y position
//now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
count++;
} else {//counter is at 1000 stop the timer
((Timer) ae.getSource()).stop();
}
}
});
t.start();
4) An alternative (because I see for now you are only moving a Rectangle which is not a Swing component) to Swing timer is TimerTask, and this can be used as long as no Swing components will be created/manipulated from within its run() method (as TimerTask does not run on EDT like Swing Timer). Note revalidate() and repaint() are Thread-safe so it can be used within TimerTask.
The advantage of the above is unnecessary code is kept of EDT (i.e moving AWT rectangle by changing co-ords) i.e
final TimerTask tt = new TimerTask() {
#Override
public void run() {
if (count < 1000) {
//increment rectangles y position
//now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
count++;
} else {//counter is at 1000 stop the timer
cancel();
}
}
};
new Timer().scheduleAtFixedRate(tt, 0, 10);//start in 0milis and call run every 10 milis

Related

How to create new instances of a timer Task instead of canceling and restarting it all over?

Well the thing is that I have a project where I have to make a game on java. In my game there's a spaceship that shoots lasers. I have the mechanics for shooting the laser more or less figured out but I am currently using a timer task to make the laser fly through the JFrame and give the impression a laser was shot.
Problem is that TimerTask seems to bug out as soon as I start shooting many times.
The main goal is to move an object across the screen at a given speed.
Is there something else I could do to achieve this? Is there a better way to implement this?
I appreciate all the help I could get, Thanks.
Here is some of the code:
public Space() {
this.setBackground(Color.BLACK);
this.setCursor(Cursor.getDefaultCursor());
this.addMouseMotionListener(new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
repaint();
x = e.getX()-spaceFighterIcon.getIconHeight()/2;
y = e.getY()-spaceFighterIcon.getIconWidth()/2;
}
public void mouseDragged(MouseEvent e) {
repaint();
x = e.getX()-spaceFighterIcon.getIconHeight()/2; //Positions the cursor on the middle of the spaceShip and viceVersa
y = e.getY()-spaceFighterIcon.getIconWidth()/2;
}
}
);
this.addMouseListener(new MouseAdapter(){
public void mousePressed(MouseEvent e) {
if(timerRunning = true){
laserTimer.cancel();
laserTimer.purge();
laserFired = false;
}
if(SwingUtilities.isLeftMouseButton(e)){ // Gets where the laser is going to be shot from
repaint();
laserX = e.getX()-spaceFighterIcon.getIconWidth()/6;
laserY = e.getY();
laserFired = true;
}
if(SwingUtilities.isRightMouseButton(e)){
}
if(SwingUtilities.isMiddleMouseButton(e)){
}
}
});
}
public void paintComponent(Graphics g) {
this.graphics = g;
super.paintComponent(g);
spaceFighterIcon.paintIcon(this, g, x, y);
if(laserFired == true){
shootLaser();
}
}
public void shootLaser(){
laserIcon.paintIcon(this, graphics, laserX, laserY-50); // paints the laser
laserTimer = new Timer();
laserTimer.schedule(new AnimateLasers(), 0, 200); // Timer to move the laser across the frame
timerRunning = true;
repaint();
}
public void lasers(){
laserY = laserY-1; // function to move the laser
if(laserY <= 0){
laserTimer.cancel();
laserTimer.purge();
}
}
public class AnimateLasers extends TimerTask {
public void run() {
lasers();
repaint();
}
}
Start by taking a look at Concurrency in Swing and How to use Swing Timers instead of java.util.Timer.
Swing Timer is safer to use with Swing, as it executes it ticks within the context of the Event Dispatching Thread
Also take a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works
Don't maintain a reference to the Graphics context outside of the paint method. Your component will be told when it should repaint it self by the system (via the call to the paintComponent method), essentially, you use the time to update the location of the "laser" and call repaint, then paint the laser within the paintComponent when it's called by the paint system

practicing paintComponent method

I want to practice paintComponent method. My program is consist of two classes(test and paintClass) in different files. I want to divide the area into 25 squares by drawing lines vertically and horizontally by using paintComponent method. My constructor only has paintComponent now. I know it is not very efficient but I will add buttons, labels and other things in the future so I need to use the program like this. When I run the program I get a nullpointerexception error.Can you help?
EDIT : I changed the page into g and added some lines into code. Still has the same error.
import javax.swing.*;
import java.awt.*;
public class test
{
public static void main(String[] args)
{
JFrame frame = new JFrame("buttons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
paintClass paint = new paintClass();//This line has error.
paint.repaint();//ADDED
frame.add(paint);
frame.pack();
frame.setVisible(true);
}
}
import javax.swing.*;
import java.awt.*;
public class paintClass extends JPanel
{
private Graphics g;
private int interval,side,number;
public paintClass()
{
this.repaint();//ADDED
paintComponent(g);//This line has error.
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);//ADDED and has an error.
this.repaint();//ADDED
side = 250;
number = 5;
interval = side / number;
g.drawRect(0,0, side, side);
for(int i = 0; i <= number - 1; i++)
{
for(int j = 0; j <= number - 1; j++)
{
g.drawLine(i * interval, 0, i * interval, side);
}
g.drawLine(0, i * interval, side, i * interval);
}
}
}
You are calling paintComponent in the paintClass's constructor with a Graphics object that has not been instantiated. For simple drawing, you shouldn't need to call this method directly - it will be called by the EDT (with the appropriate Graphics object) when necessary (in other words, remove that line and don't hold onto a reference to the Graphics object).
//constructor of Class - note Classnames should start with uppercase
public paintClass(){
//no need to call paintComponent or repaint here
}
You can request a repaint by calling the repaint() method defined by JComponent (the parent class of JPanel). You should also call the parent method
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
//do your custom drawing here, and never call repaint from this method
}
I would recommend, if you have not yet, is to study the Oracle tutorials about Custom painting: http://docs.oracle.com/javase/tutorial/uiswing/painting/
First rule of painting in Swing, you don't control the paint process. Swing will paint when and if it wants. The best you can do is provide hints to the system that you would like something updated.
Never maintain a reference to a Graphics or to you didn't create yourself
Never call repaint directly or indirectly from inside any paint method, this will set up a recursive paint cycle which will eventually consume your CPU
It's pointless to call repaint on a component which isn't displayable on the screen
For example
public class paintClass extends JPanel
{
private int interval,side,number;
public paintClass()
{
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
side = 250;
number = 5;
interval = side / number;
g.drawRect(0,0, side, side);
for(int i = 0; i <= number - 1; i++)
{
for(int j = 0; j <= number - 1; j++)
{
g.drawLine(i * interval, 0, i * interval, side);
}
g.drawLine(0, i * interval, side, i * interval);
}
}
}
You need to Override the paintComponent(Graphics g) not to create one. Also, if you want the paintComponent(...) to be executed, call repaint() on that component, do not call paintComponent(...) directly.
In your class "paintClass", you should instantiate the page var :
public paintClass()
{
page = new Graphics();
paintComponent(page);
}

Understanding the EDT in a real model with frequent updates

I am writing the Sugarscape simulation in Java and need a working GUI. Sugarscape is a spatial landscape consisting of tiles (of sugar), and agents moving and consuming sugar. For simplicity, I have only one agent and no sugar- I just want to see the agent moving.
For the past 2 weeks I have read into painting in java, concurrency in java, concurrency in swing, I have read filthy rich clients and countless StackOverflow threads, but I must resort to asking a question here.
I need my model separate from the GUI. This presents a problem since 99% of tutorials suggest to call for repaint within other methods. My idea was to run one "tick" of the simulation: all agents move, and then send an Event (my GUI class extends Observer) which then triggers a repaint(); request and update the GUI. However the problem (the misunderstanding) lies with the SwingUtilities.InvokeLater method. My code is:
public void setupGUI()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
System.out.println("GUI is being setup, on EDT now? " + SwingUtilities.isEventDispatchThread());
SugarFrame frame = new SugarFrame(simulation.getWorld());
frame.setVisible(true);
}
});
}
For understanding what is happening I have inserted println's everywhere. The order of events is what confuses me:
Console output:
1.Agent created. Starting Position: X= 19 Y= 46 // This is in the Agent constructor
2.Simulation start. Experiment number: 0
GUI is being setup, on EDT now? true // As you see above, this is WITHIN the SwingUtilities.InvokeLater section. But then the EDT pauses and the real model continues:
Tick number 0
Invoke Agent Actions, fire TickStart Event
TickStartEvent created
Invoke Agent Actions, for-loop starting now
Agent number 0 moving now:
Consuming Sugar now.
Moving now.
Sleeping now.
The Sugarframe has been created and Grid added. All on EDT? true // And there it is back again. The paint component follows and the window with the Agent visible appears.
paintComponent called, on EDT? true
Now, I have read that by putting the main thread to sleep, you give the EDT time to run the repaint. However, this only happens once. Repaint is never called again, and I only ever see one iteration of the model.
I simply do not understand what piece of information I am missing to work with the EDT properly. Swingworker and Swingtimer are suggested regularly, but for every suggestion there is a notion that they are not needed for a model such as mine. Either paintComponent is not called at all, or queued up until the end (and then still not repainting, even if I use thread.sleep).
I'd appreciate any help. Apologies for the long post.
//Edit: as per request some more code.
The entire main method:
public class SimulationController {
static Simulation simulation;
public static final int NUM_EXPERIMENTS = 1;
public SimulationController()
{
Random prng = new Random();
SimulationController.simulation = new Simulation(prng);
}
public void run() {
setupGUI();
for(int i=0; i<NUM_EXPERIMENTS; i++) {
System.out.println("Simulation start. Experiment number: " + i);
simulation.getWorld().addObserver(simulation);
simulation.addObserver(simulation.getWorld());
simulation.run();
}
}
public void setupGUI()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run() {
System.out.println("GUI is being setup, on EDT now? " + SwingUtilities.isEventDispatchThread());
SugarFrame frame = new SugarFrame(simulation.getWorld());
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
SimulationController controller = new SimulationController();
controller.run();
}
}
The paint override in my JPanel class:
#Override
public void paintComponent(Graphics g) {
System.out.println(">>>>>>>>paintComponent called, on EDT? " + SwingUtilities.isEventDispatchThread()+"<<<<<<<<<<");
super.paintComponent(g);
//g.clearRect(0, 0, getWidth(), getHeight());
rectWidth = getWidth() / world.getSizeX();
rectHeight = getHeight() / world.getSizeY();
for (int i = 0; i < world.getSizeX(); i++)
{
for (int j = 0; j < world.getSizeY(); j++)
{
// Upper left corner of this terrain rect
x = i * rectWidth;
y = j * rectHeight;
Tile tile = world.getTile(new Position(i, j));
if (tile.hasAgent())
{
g.setColor(Color.red);
} else
{
g.setColor(Color.black);
}
g.fillRect(x, y, rectWidth, rectHeight);
}
}
}
JPanel class again, update methods:
public void update(Observable o, Object arg)
{
if (arg instanceof TickEnd)
{
TickEvent tickEndevent = new TickEvent();
this.addTickEvent(tickEndevent);
}
}
}
private final BlockingQueue<TickEvent> TICK_EVENTS = new LinkedBlockingQueue<TickEvent>();
/**Runnable object that updates the GUI (I think)**/
private final Runnable processEventsRunnable = new Runnable()
{
public void run()
{
TickEvent event = new TickEvent();
while ((event = TICK_EVENTS.poll()) != null)
{
System.out.println("This is within processEventsRunnable, inside the While loop. Repaint is called now.");
repaint();
}
}
};
/**Add Event to the processing-Events-queue**/
public void addTickEvent(TickEvent event)
{
//System.out.println("This is in the Add TickEvent method, but before the adding. "+TICK_EVENTS.toString());
TICK_EVENTS.add(event);
System.out.println("TickEvent has been added! "+TICK_EVENTS.toString() + "On EDT?" + SwingUtilities.isEventDispatchThread());
if (TICK_EVENTS.size() >= 1)
{
SwingUtilities.invokeLater(processEventsRunnable);
}
}
And last but not least, the JFrame constructor:
/** Sugarframe Constructor**/
public SugarFrame(World world)
{
super("Sugarscape"); // creates frame, the constructor uses a string argument for the frame title
grid = new Grid(world); // variable is declared in the class
add(grid);
setDefaultCloseOperation(EXIT_ON_CLOSE); // specifies what happens when user closes the frame. exit_on_close means the program will stop
this.setContentPane(grid);
this.getContentPane().setPreferredSize(new Dimension(500, 500));
this.pack(); // resizes frame to its content sizes (rather than fixed height/width)
System.out.println("The Sugarframe has been created and Grid added. All on EDT? "+ SwingUtilities.isEventDispatchThread());
this.setVisible(true); // makes the Frame appear on screen
}
The sentences,
I need my model separate from the GUI. This presents a problem since 99% of tutorials suggest to call for repaint within other methods.
and
Now, I have read that by putting the main thread to sleep, you give the EDT time to run the repaint.
don't sound quite right to me, so I'll try to clear things up a bit and maybe If you reevaluate the fundamental ideas you had behind those statements you can find the piece of information that you were missing.
First of all, always keep in mind this scheduling model that we were talking about. You can not say "EDT do this for me now!". It is always "EDT here's one more task you need to do, do it when you are done with whatever you are doing". So the EDT has a queue of "tasks" to do and goes through it consuming one by one.
These tasks are usually created by events: pressing a button gives the EDT a task to do, when the state of a component of the GUI changes some listeners may be notified and enqueue some work in the EDT. However, you can also straight up say "EDT execute this piece of code, later". This is what you do with invokeLater, you schedule a work to do in the EDT whenever it's free. Even if you call invokeLater from the EDT the task is scheduled, not executed at the moment.
The same happens with invokeAndWait yes, the code is executed sequentially as if it was executed at the moment, but it is still an scheduled work. So repaint() is no exception to this. repaint() doesn't repaint the GUI, but rather schedules the repainting of the GUI.
However repaint() is exceptional in the sense that it can be called from outside the EDT! This is not surprising now that we know that the only thing that does is scheduling a certain work, it does not actually mess with the GUI so you can call it wherever you want.
This means that the line
SwingUtilities.invokeLater(processEventsRunnable);
where processEventsRunnable basically executes a repaint() is meaningless and the whole tick system overly complex and unnecesary. You just have to call repaint() when you change something on the GUI or on the data that the GUI feeds on so the changes are reflected on the screen.
Furthermore, if you wanted to do something that needs to be executed in the EDT (like changing the text of a Label with the score) you can just put that code in an invokeLater block in your main thread. That will queue and execute the task properly, you don't need to do your own event queue system.
Keeping all this in mind the following makes no sense:
I have read that by putting the main thread to sleep, you give the EDT time to run the repaint
The GUI will be updated on its own shortly after you call repaint(). The main doing a lot of things and calling a lot of repaints does not prevent the GUI from being updated. However, if you want to "sleep" the main so the pace of the changes is slow so the user can appreciate it on the screen, you should use a timer.
So, as long as your main is not accessing GUI values and methods, feel free to call repaint whenever you are done changing the data, periodically or not.
Edit: Also it sounds a little bit weird that you have a main thread doing things. As you read in the concurrency chapter, usually you just create the GUI in the EDT and then the application is mostly event-driven when buttons are pressed and such. If you need to do changes periodically use a timer. You can use auxiliar threads to do specific non-GUI related heavy work, like reading a file. But you don't usually have an auxiliar thread permanently active as part of the design.
The following is a very simple program that moves an square periodically. I just use a timer to change the data and call repaint(). Note that I'm using a SwingTimer (it is executed in the EDT) since I wanted to check the panel width. Otherwise I could run the code of the timer in any thread.
In your case you probably have your "map" stored independently of the GUI, so you just need to check that data to properly move the coordinates of the agent whenever you want (on keyboard press, periodically...).
It looks like this:
Full code:
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class MovingSquareTest
{
int x, y, size, step;
MyPanel panel;
Timer timer;
public static final void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
MovingSquareTest app = new MovingSquareTest();
app.createAndShowGUI();
app.timer.start();
}
});
}
public MovingSquareTest()
{
x = 0;
y = 150;
size = 50;
step = 50;
timer = new Timer(500, new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
x += step;
if (x < 0) x = 0;
if (x + size > panel.getWidth()) x = panel.getWidth() - size;
if (x == 0 || x + size == panel.getWidth()) step *= -1;
panel.repaint();
}
});
}
public void createAndShowGUI()
{
JFrame frame = new JFrame("Dance, my square!");
panel = new MyPanel();
frame.add(panel);
frame.setSize(600, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private class MyPanel extends JPanel
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawRect(x, y, size, size);
}
}
}

Move JPanel in JFrame

I'm looking to move a jpanel inside of a JFrame, and it won't seem to budge. I can set it's location in the paint() method, but it won't update in repaint. Please help! Here is my code:
public void paint(Graphics g) {
g.drawImage(playerImg, x, 50, null);
this.setLocation(x, 50);
}
public void update() {
this.repaint();
}
public void keyPressed(KeyEvent key) {
if(key.getKeyCode() == KeyEvent.VK_UP) {
x = x + 50;
System.out.println("e");
update();
}
}
"I can set it's location in the paint() method" - Don't, seriously, you should never modify the state of any component within any paint method, in fact, you've broken the paint chain by not calling super.paint, which is going to cause you no end of other problems.
Instead, set the parent containers layout manager to null, you will now find that the component disappears. This is because the layout manager is responsible for setting the size and position of the component, which you will have to take over control of.
Instead of overriding paint you should be overriding paintComponent and calling super.paintComponent. Take a look at Performing Custom Painting for more details

Updating my Graphics

I'm just starting to learn about programming in Java and even more recently with graphics, and I've run into some problems.
I want to create a game like dwarf fortress in look, with colored text instead of images.
This is what I have so far:
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.red);
for (int i = 0; i < 50; i++) {
g.drawString("[Game goes here]", 100, 150);
g.dispose();
System.out.println(i);
}
g.dispose();
}
public GTest() {
setSize(Toolkit.getDefaultToolkit().getScreenSize().width / 3, Toolkit
.getDefaultToolkit().getScreenSize().width / 3 + 50);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String[] args) {
GTest myWindow = new GTest();
}
I want it to update the graphics on a timer, but I'm not really sure how to do this.
I know that this is a pretty broad question and I would be happy to clarify anything you might want to know.
EDIT:
So I added this bit:
String[] letters = new String[10];
float fontsize = Toolkit.getDefaultToolkit().getScreenSize().width / 30;
public void paint(Graphics g) {
g.setColor(textColor);
setFont(getFont().deriveFont(fontsize));
for(int i = 0; i < 10; i++){
if((int) (Math.random() * 100) > 97){
letters[i] = "w";
textColor = new Color(0, 0, 100);
}else{
letters[i] = "l";
textColor = new Color(0, 100, 0);
}
g.drawString(letters[i], i * 3, 10);
}
But now it doesn't display at all. I added a sysout after the g.drawString and it performed it so I'm not sure what the problem is.
When doing anything based on a timer in Swing, the javax.swing.Timer class is your best friend.
It's JavaDocs explains its usage pretty well, so here's an example.
public class GTest extends JFrame implements ActionListener {
private Color textColor = Color.BLACK;
private Random random = new Random();
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(textColor);
g.drawString("[Game goes here]", 100, 150);
}
#Override
public void actionPerformed(ActionEvent e) {
textColor = new Color(random.nextInt(0x00ffffff));
repaint();
}
public GTest() {
setSize(Toolkit.getDefaultToolkit().getScreenSize().width / 3,
Toolkit.getDefaultToolkit().getScreenSize().width / 3 + 50);
setDefaultCloseOperation(EXIT_ON_CLOSE);
Timer timer = new Timer(500, this);
timer.setInitialDelay(0);
timer.start();
setVisible(true);
}
public static void main(String[] args) {
GTest myWindow = new GTest();
}
}
It's your GTest class once again, but this time the text color changes automatically every 0.5 seconds.
Notice two main changes:
The constructor now sets up a new instance of Timer with no initial delay, period of 500 ms and its listener set up to this. That means that this constructed instance will listen to that timer's ticks.
To do that, we needed to implement the ActionListener interface. This forces us to write the actionPerformed() method which gets called every time the Timer ticks. In this method, we change the textcolor to a random one and call repaint() which subsequently calls our paint() method and gets the text written.
P.S. You don't have to dispose() your Graphics object every time. It's actually said in its JavaDoc, too (emphasize mine):
Graphics objects which are provided as arguments to the paint() and
update() methods of components are automatically released by the system
when those methods return. For efficiency, programmers should call
dispose() when finished using a Graphics object only if it was created
directly from a component or another Graphics object.
First of all, if you don't create a copy of the Graphics context, you shouldn't be disposing of it. This could actually prevent other parts of your application form been painted ;)
Second of all. I would avoid extending from a top level container, like JFrame, apart from allowing you to draw under the frame/border decoration of the window, they aren't double buffered.
Instead, I'd use something like a JPanel instead and override its paintComponent method. This will provide you with automatic double buffering.
Because Swing is a single threaded framework, it is expected that all updates to the UI be executed within the context of the Event Diapatching Thread.
This makes live a little difficult when it comes to try to do things like waiting and synchronizing paint updates.
Luckly, Swing provides a javax.swing.Timer which allows you schedule an event for some time in the future. This can also be setup to repeat and regular intervals.
Timer timer = new Timer(40, new ActionListener() {
public void actionPerformed(ActionEvent e) {
// perform your required actions here
}
});
Now, beware, the actionPerformed method is being executed with the context of the EDT, this means, that any long running/time consuming processing you do here may cause you UI to stop painting
Take a look at
Performing Custom Painting
Intial Threads
Concurrency in Swing
For more details...

Categories