Reputation: 626
Im making a Simon Says game and when I call the randomColorChange() method in the KeyListener pressed() method, it keeps the winow from closing. The randomColorChange() method changes colors randomly. After the method is finished, I want the keyPressed() method to light up the keys:
public void randomColorChange(){
decrement = simonIncrease;
try{
int random;
for (int i = 0; i < simonIncrease; i++)
{
random = (int) (Math.random() * 4);
Thread.sleep(lightUpSpd);
if (random == 0)
{
green = green.brighter();
repaint();
Thread.sleep(lightUpSpd);
green= green.darker();
repaint();
}
if (random == 1)
{
red = red.brighter();
repaint();
Thread.sleep(lightUpSpd);
red = red.darker();
repaint();
}
if (random == 2)
{
blue = blue.brighter();
repaint();
Thread.sleep(lightUpSpd);
blue = blue.darker();
repaint();
}
if (random == 3)
{
yellow = yellow.brighter();
repaint();
Thread.sleep(lightUpSpd);
yellow = yellow.darker();
repaint();
}
}
}
catch (InterruptedException e){
e.printStackTrace();
}
}
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_DOWN)
{
blue = blue.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT)
{
red = red.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_UP)
{
green = green.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
{
yellow = yellow.brighter();
repaint();
}
decrement--;
if (decrement == 0)
{
simonIncrease++;
randomColorChange();
decrement = simonIncrease;
}
}
The problem is that the segments will light up, but when I add the randomColorChange() method after simonIncrease++, the program doesn't work at all and I can't close the window
Here's the whole class:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Arc2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class SimonShape extends JFrame implements KeyListener {
private int width;
private int height;
private int x;
private int y;
private int TURN = 45;
private int simonIncrease = 1;
private int lightUpSpd = 1000;
private int decrement = simonIncrease;
private Color blue = Color.BLUE.darker();
private Color red = Color.RED.darker();
private Color yellow = Color.YELLOW.darker();
private Color green = Color.GREEN.darker();
public SimonShape(int width, int height, int x, int y) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;
JLabel label = new JLabel();
setSize(800, 800);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
label.addKeyListener(this);
label.setFocusable(true);
label.setOpaque(true);
label.addKeyListener(this);
this.add(label);
setVisible(true);
label.requestFocusInWindow();
randomColorChange();
}
public void randomColorChange() {
decrement = simonIncrease;
try {
int random;
for (int i = 0; i < simonIncrease; i++) {
random = (int) (Math.random() * 4);
Thread.sleep(lightUpSpd);
if (random == 0) {
green = green.brighter();
repaint();
Thread.sleep(lightUpSpd);
green = green.darker();
repaint();
}
if (random == 1) {
red = red.brighter();
repaint();
Thread.sleep(lightUpSpd);
red = red.darker();
repaint();
}
if (random == 2) {
blue = blue.brighter();
repaint();
Thread.sleep(lightUpSpd);
blue = blue.darker();
repaint();
}
if (random == 3) {
yellow = yellow.brighter();
repaint();
Thread.sleep(lightUpSpd);
yellow = yellow.darker();
repaint();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
blue = blue.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
red = red.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_UP) {
green = green.brighter();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
yellow = yellow.brighter();
repaint();
}
decrement--;
if (decrement == 0) {
simonIncrease++;
randomColorChange();
decrement = simonIncrease;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
green = green.darker();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
blue = blue.darker();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
yellow = yellow.darker();
repaint();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
red = red.darker();
repaint();
}
}
public void keyTyped(KeyEvent e) {
}
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// Blue Section
g2.setStroke(new BasicStroke(2.0f));
g2.setPaint(blue);
g2.fill(new Arc2D.Double(x, y, width, height, 180 + TURN, 90, Arc2D.PIE));
// Red Section
g2.setStroke(new BasicStroke(2.0f));
g2.setPaint(red);
g2.fill(new Arc2D.Double(x, y, width, height, 90 + TURN, 90, Arc2D.PIE));
// Yellow Section
g2.setStroke(new BasicStroke(2.0f));
g2.setPaint(yellow);
g2.fill(new Arc2D.Double(x, y, width, height, -90 + TURN, 90, Arc2D.PIE));
// Green Section
g2.setStroke(new BasicStroke(2.0f));
g2.setPaint(green);
g2.fill(new Arc2D.Double(x, y, width, height, 360 + TURN, 90, Arc2D.PIE));
}
}
Test Class:
public class SimonTest {
public static void main(String[] args)
{
new SimonShape(500,500,150,150);
}
}
Upvotes: 1
Views: 151
Reputation: 285403
You're calling Thread.sleep(...)
on the Swing event thread which will sleep or lock the entire GUI. Don't do this. Use a Swing Timer instead.
Also:
paintComponent(Graphics g)
method and not directly in the JFrame or in an override of its paint(Graphics g)
method. This will help prevent your colors from flickering as they're doing.paintComponent(Graphics g)
method, be sure to call the super.paintComponent(g)
method at the start, so your component can do its graphic house keeping first.For Example:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Arc2D;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.*;
/**
* link: http://stackoverflow.com/questions/21867283/method-keeps-window-from-
* closing
*
* @author Pete
*
*/
@SuppressWarnings("serial")
public class SimonPanelTest extends JPanel {
private static final String PRESSED = "pressed";
private static final String RELEASED = "released";
private static final int TIMER_DELAY = 1000;
private static final int TIME_SLICES = 8;
private Random random = new Random();
private SimonPanel simonPanel = new SimonPanel();
public SimonPanelTest() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(new ShowRandomPatternAction()));
setLayout(new BorderLayout());
add(simonPanel, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
setKeyBindings(simonPanel, KeyEvent.VK_UP, MyColor.GREEN);
setKeyBindings(simonPanel, KeyEvent.VK_RIGHT, MyColor.YELLOW);
setKeyBindings(simonPanel, KeyEvent.VK_DOWN, MyColor.BLUE);
setKeyBindings(simonPanel, KeyEvent.VK_LEFT, MyColor.RED);
simonPanel.addPropertyChangeListener(SimonPanel.MY_COLOR, pce -> {
System.out.println(pce.getNewValue());
});
}
private void setKeyBindings(SimonPanel panel, int keyCode, MyColor myColor) {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inMap = panel.getInputMap(condition);
ActionMap actMap = panel.getActionMap();
KeyStroke keyPressed = KeyStroke.getKeyStroke(keyCode, 0, false);
KeyStroke keyReleased = KeyStroke.getKeyStroke(keyCode, 0, true);
inMap.put(keyPressed, myColor.toString() + PRESSED);
inMap.put(keyReleased, myColor.toString() + RELEASED);
actMap.put(myColor.toString() + PRESSED, new MyKeyAction(panel, myColor, true));
actMap.put(myColor.toString() + RELEASED, new MyKeyAction(panel, myColor, false));
}
private class ShowRandomPatternAction extends AbstractAction {
private static final int MIN_RANDOM_COLORS = 5;
private static final int MAX_RANDOM_COLORS = 10;
public ShowRandomPatternAction() {
super("Show Random Pattern");
putValue(MNEMONIC_KEY, KeyEvent.VK_S);
}
@Override
public void actionPerformed(ActionEvent e) {
List<MyColor> colorList = new ArrayList<MyColor>();
for (int i = 0; i < random.nextInt(MAX_RANDOM_COLORS - MIN_RANDOM_COLORS)
+ MIN_RANDOM_COLORS; i++) {
int colorIndex = random.nextInt(MyColor.values().length);
MyColor myColor = MyColor.values()[colorIndex];
colorList.add(myColor);
}
ActionListener timerListener = new TimerListener(simonPanel, colorList);
Timer timer = new Timer(TIMER_DELAY / TIME_SLICES, timerListener);
timer.start();
}
}
private class TimerListener implements ActionListener {
@SuppressWarnings("hiding")
private SimonPanel simonPanel;
private int colorListIndex = 0;
private int sliceCount = 0;
private List<MyColor> myColorList;
private int maxCount;
public TimerListener(SimonPanel simonPanel, List<MyColor> myColorList) {
this.simonPanel = simonPanel;
this.myColorList = myColorList;
maxCount = myColorList.size();
}
@Override
public void actionPerformed(ActionEvent evt) {
if (colorListIndex == maxCount) {
for (MyColor myColor : MyColor.values()) {
simonPanel.setMyColorPressed(myColor, false);
}
((Timer) evt.getSource()).stop();
return;
}
if (sliceCount == 0) {
MyColor myColor = myColorList.get(colorListIndex);
simonPanel.setMyColorPressed(myColor, true);
sliceCount++;
} else if (sliceCount < TIME_SLICES - 1) {
sliceCount++;
return;
} else if (sliceCount == TIME_SLICES - 1) {
sliceCount = 0;
MyColor myColor = myColorList.get(colorListIndex);
simonPanel.setMyColorPressed(myColor, false);
colorListIndex++;
return;
}
}
}
private class MyKeyAction extends AbstractAction {
private SimonPanel panel;
private MyColor myColor;
private boolean pressed;
public MyKeyAction(SimonPanel panel, MyColor myColor, boolean pressed) {
this.panel = panel;
this.myColor = myColor;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent evt) {
panel.setMyColorPressed(myColor, pressed);
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("Simon Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new SimonPanelTest());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
@SuppressWarnings("serial")
class SimonPanel extends JPanel {
public static final String MY_COLOR = "my color";
private static final int PREF_W = 600;
private static final int PREF_H = PREF_W;
private static final int ARC_ANGLE = 90;
private Map<MyColor, MyArc> colorPressedMap = new EnumMap<MyColor, MyArc>(MyColor.class);
private List<MyArc> myArcs = new ArrayList<>();
public SimonPanel() {
int i = 0;
for (MyColor myColor : MyColor.values()) {
int startAngle = 45 - i * 90;
Arc2D arc = new Arc2D.Double(0, 0, PREF_W, PREF_H, startAngle, ARC_ANGLE, Arc2D.PIE);
MyArc myArc = new MyArc(arc, myColor);
myArcs.add(myArc);
colorPressedMap.put(myColor, myArc);
i++;
}
addMouseListener(new MyMouse());
}
@Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
public void setMyColorPressed(MyColor myColor, boolean pressed) {
colorPressedMap.get(myColor).setSelected(pressed);
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (MyColor myColor : MyColor.values()) {
colorPressedMap.get(myColor).fill(g2);
}
}
private class MyMouse extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (MyArc myArc : myArcs) {
if (myArc.contains(e.getPoint())) {
myArc.setSelected(true);
firePropertyChange(MY_COLOR, null, myArc.getMyColor());
repaint();
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.getButton() != MouseEvent.BUTTON1) {
return;
}
for (MyArc myArc : myArcs) {
myArc.setSelected(false);
}
repaint();
}
}
}
class MyArc {
private Arc2D arc;
private MyColor myColor;
private boolean selected;
public MyArc(Arc2D arc, MyColor myColor) {
this.arc = arc;
this.myColor = myColor;
}
public boolean contains(Point p) {
return arc.contains(p);
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public Arc2D getArc() {
return arc;
}
public MyColor getMyColor() {
return myColor;
}
public Color getColor() {
return selected ? myColor.getBrightColor() : myColor.getDarkColor();
}
public void fill(Graphics2D g2) {
Color oldColor = g2.getColor();
g2.setColor(getColor());
g2.fill(arc);
g2.setColor(oldColor);
}
}
enum MyColor {
GREEN(Color.green.brighter(), Color.green.darker()),
YELLOW(Color.yellow.brighter(), Color.yellow.darker()),
BLUE(Color.blue.brighter(), Color.blue.darker()),
RED(Color.red.brighter(), Color.red.darker());
private MyColor(Color brightColor, Color darkColor) {
this.brightColor = brightColor;
this.darkColor = darkColor;
}
private Color brightColor;
private Color darkColor;
public Color getBrightColor() {
return brightColor;
}
public Color getDarkColor() {
return darkColor;
}
}
Which displays as:
Upvotes: 6