方法使窗口无法关闭

时间:2014-02-18 22:55:36

标签: java swing

我正在制作一个Simon说游戏,当我在KeyListener的按()方法中调用randomColorChange()方法时,它会让winow不会关闭。 randomColorChange()方法随机更改颜色。方法完成后,我希望keyPressed()方法点亮键:

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

}

问题是段会亮起,但是当我在simonIncrease ++之后添加randomColorChange()方法时,程序根本无法工作,我无法关闭窗口

以下是全班:

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

   }
}

测试类:

public class SimonTest  {

public static void main(String[] args)
{
    new SimonShape(500,500,150,150);
}

}

1 个答案:

答案 0 :(得分:5)

您正在Swing事件线程上调用Thread.sleep(...),该线程将睡眠或锁定整个GUI。不要这样做。请改用Swing Timer。

此外:

  • 您应该避免在Swing应用程序中使用KeyListeners,而应该使用Key Bindings。
  • 您应该在JPanel的paintComponent(Graphics g)方法的覆盖中绘制,而不是直接在JFrame中或在其paint(Graphics g)方法的覆盖中绘制。这有助于防止你的颜色在他们正在做的时候闪烁。
  • 务必在油漆覆盖中调用超级油漆方法。例如,当覆盖JPanel的paintComponent(Graphics g)方法时,请务必在开始时调用super.paintComponent(g)方法,以便您的组件可以先保留其图形内容。
  • 您需要设置Graphics2D的RenderingHints以允许消除锯齿以平滑图形。

例如:

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

显示为:

enter image description here