I'm using a Timer to toggle a boolean, but instead of firing every 250ms like it's supposed to, it fires as fast as it can. Here is my code:
package com.cgp.tetris;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.imageio.ImageIO;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.sound.sampled.DataLine.Info;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
public class SinglePlayerMenu extends JPanel implements Runnable {
private static final long serialVersionUID = 1L;
private Thread thread;
private AudioInputStream themestream, blipstream;
private Clip clip, blipclip;
private BufferedImage base, bi1, bi2, bi3, bi4, bi1s, bi2s, bi3s, bi4s;
private boolean typeselected = false, b1 = true, b2 = false, b3 = true, b4 = false, b5 = false, b6 = false, b1a = true, b2a = false;
public SinglePlayerMenu() {
super();
this.addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent e) {
SinglePlayerMenu.this.requestFocusInWindow();
}
});
}
public void addNotify() {
super.addNotify();
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
super.paint(g);
g.drawImage(base, 0, 0, 640, 576, null);
if (b1) {
g.drawImage(bi1s, 80, 156, 240, 40, null);
} else if (!b1) {
g.drawImage(bi1, 80, 156, 240, 40, null);
}
if (b2) {
g.drawImage(bi2s, 324, 156, 236, 40, null);
} else if (!b2) {
g.drawImage(bi2, 324, 156, 236, 40, null);
}
if (b3) {
g.drawImage(bi1s, 80, 380, 240, 40, null);
} else if (!b3) {
g.drawImage(bi1, 80, 380, 240, 40, null);
}
if (b4) {
g.drawImage(bi2s, 324, 380, 236, 40, null);
} else if (!b4) {
g.drawImage(bi2, 324, 380, 236, 40, null);
}
if (b5) {
g.drawImage(bi3s, 80, 444, 240, 40, null);
} else if (!b5) {
g.drawImage(bi3, 80, 444, 240, 40, null);
}
if (b6) {
g.drawImage(bi4s, 324, 444, 236, 40, null);
} else if (!b6) {
g.drawImage(bi4, 324, 444, 236, 40, null);
}
}
public void run() {
sound();
loadImages();
bind();
while (true) {
repaint();
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
checks();
}
}
private void checks() {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
System.out.println("Being run");
if (b1a && !typeselected) {
b1 = !b1;
}
}
}, java.util.Calendar.getInstance().getTime(), 250);
}
private void bind() {
InputMap im = getInputMap();
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke("LEFT"), "left");
am.put("left", new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if (!typeselected) {
if (!b1a) {
blipclip.start();
blipclip.setFramePosition(0);
}
b1 = true;
b2 = false;
b1a = true;
b2a = false;
} else if (typeselected) {
}
}
});
im.put(KeyStroke.getKeyStroke("RIGHT"), "right");
am.put("right", new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if (!typeselected) {
if (!b2a) {
blipclip.start();
blipclip.setFramePosition(0);
}
b2 = true;
b1 = false;
b1a = false;
b2a = true;
} else if (typeselected) {
}
}
});
im.put(KeyStroke.getKeyStroke("SPACE"), "space");
am.put("space", new AbstractAction() {
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
if (!typeselected) {
typeselected = true;
b1=b1a;
b2=b2a;
} else if (typeselected) {
}
}
});
}
private void loadImages() {
try {
base = ImageIO.read(new File("res/base.png"));
bi1 = ImageIO.read(new File("res/1.png"));
bi2 = ImageIO.read(new File("res/2.png"));
bi3 = ImageIO.read(new File("res/3.png"));
bi4 = ImageIO.read(new File("res/4.png"));
bi1s = ImageIO.read(new File("res/1s.png"));
bi2s = ImageIO.read(new File("res/2s.png"));
bi3s = ImageIO.read(new File("res/3s.png"));
bi4s = ImageIO.read(new File("res/4s.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
private void sound() {
File theme = new File("res/playtheme.wav");
try {
themestream = AudioSystem.getAudioInputStream(theme);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
DataLine.Info info = new DataLine.Info(Clip.class, themestream.getFormat());
clip = null;
try {
clip = (Clip) AudioSystem.getLine(info);
} catch (LineUnavailableException e) {
e.printStackTrace();
}
try {
clip.open(themestream);
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
File blip = new File("res/blip.wav");
try {
blipstream = AudioSystem.getAudioInputStream(blip);
} catch (UnsupportedAudioFileException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
DataLine.Info blipinfo = new DataLine.Info(Clip.class, blipstream.getFormat());
blipclip = null;
try {
blipclip = (Clip) AudioSystem.getLine(blipinfo);
} catch (LineUnavailableException e) {
e.printStackTrace();
}
try {
blipclip.open(blipstream);
} catch (LineUnavailableException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void startClip() {
clip.loop(Clip.LOOP_CONTINUOUSLY);
blipclip.start();
blipclip.setFramePosition(0);
}
}
Sadly, Eclipse is acting weird, so an SSCCE won't be possible ATM.
You basic code looks wrong to me:
Custom painting should be done in the paintComponent() method.
When working with Swing you should be using a Swing Timer.
You have a Thread that repaints every 2ms. Is that your problem?
You don't need a Thread with a while () loop. That is what you use a Timer for. So I would guess the Thread and the Timer should be combined into a single Swing Timer. When the time fires you update your variables and then invoke repaint().
From Timer.scheduleAtFixedRate-documentation:
If your task takes longer than 250ms to execute, the following task will be executed right after the first task, and the one following that, etc. Maybe you meant to use Timer.schedule instead?