颜色类不改变颜色

时间:2015-05-12 21:39:22

标签: java swing user-interface

我正在制作Simon说的游戏。我遇到的一个问题是,在第一级之后,我的颜色不会改变/亮起。我跟踪代码并包含print语句以确保代码也正常工作。

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

 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 level = 1;

//speed of the light up sequence
private int lightUpSpd = 500;

//chooses random color based on numbers 0-3
private int random;

//keeps track of user inputs 
private int compCounter = 0;

ArrayList<Integer> comp = new ArrayList<Integer>();


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.setFocusable(true);
    label.setOpaque(true);
    label.addKeyListener(this);
    this.add(label);
    setVisible(true);
    label.requestFocusInWindow();


    randomColorChange();
}


private void randomColorChange()
{
    try
    {
        JOptionPane.showMessageDialog(this, "Level " + level);
        random = (int) (Math.random() * 4);
        comp.add(random);

        //light up sequence
        for (int i = 0; i < level; i++)
        {

            if (comp.get(i) == 0)
            {
                green = green.brighter();
                System.out.println("light");
                repaint();
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                green = green.darker();
                repaint();
            }

            else if (comp.get(i) == 1)
            {
                red = red.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                red = red.darker();
                repaint();
            }

            else if (comp.get(i) == 2)
            {
                blue = blue.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                blue = blue.darker();
                repaint();
            }

            else {

                yellow = yellow.brighter();
                repaint();
                System.out.println("light");
                Thread.sleep(lightUpSpd);
                System.out.println("dark");
                yellow = yellow.darker();
                repaint();
            }

            Thread.sleep(lightUpSpd/2);
        }


    }
        catch (InterruptedException e){
            e.printStackTrace();
        }

}

public void keyPressed(KeyEvent e)
{   

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

}


public void keyReleased(KeyEvent e) {

    if (e.getKeyCode() == KeyEvent.VK_UP)
    {
        green = green.darker();
        repaint();

        if (0 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect, end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_DOWN)
    {
        blue = blue.darker();
        repaint();

        if (2 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;

                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_RIGHT)
    {
        yellow = yellow.darker();
        repaint();

        if (3 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }

    if (e.getKeyCode() == KeyEvent.VK_LEFT)
    {
        red = red.darker();
        repaint();
        //user.add(1);
        if (1 == comp.get(compCounter))
        {
            compCounter++;

            if (compCounter == comp.size())
            {
                // next level
                // reset compCounter
                JOptionPane.showMessageDialog(this, "Correct!");
                lightUpSpd = lightUpSpd - 5;
                level++;
                compCounter = 0;
                randomColorChange();
            }
        }
        else
        {
            //incorrect; end game;
            JOptionPane.showMessageDialog(this, "Incorrect");
            this.setVisible(false);
            this.dispose();
            return;
        }


    }
}

public void keyTyped(KeyEvent e) {}

public void paint(Graphics g)
{

    Graphics2D g2 = (Graphics2D) g;


    // Blue Section
    g2.setStroke(new BasicStroke(1.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));

}
}

1 个答案:

答案 0 :(得分:5)

看起来你正在尝试将Swing GUI编写为线性控制台程序,我很惊讶它的工作原理。如果您不介意,请让我提供一些建议:

  1. 不要直接在JFrame的绘制方法中绘制,因为这会弄乱GUI的图形。你没有调用JFrame的super.paint(g)方法,所以如果你的程序发展得很难调试绘画问题和工件,那就不会让我感到惊讶,因为你在一个非常关键的时刻打破了绘画链。
  2. 相反,如果您必须使用Graphics进行绘制,请在JPAnel的paintComponent覆盖中执行此操作。
  3. 不要像在Swing GUI中那样调用Thread.sleep(...),因为如果您不了解Swing线程规则并注意,则可能会使整个GUI处于睡眠状态。相反,如果您需要延时,请使用Swing Timer。
  4. 这是一个事件驱动的GUI程序,因此for循环无法提升级别。而是让用户与GUI交互,并通过GUI的状态来基于GUI的响应,而不需要用于循环的线性编程类型。这是学习事件驱动编程时最难掌握的概念之一,但却是一个关键概念。
  5. 干:不要重复自己。您有很多重复的代码,可以轻松地合并到方法中,这样做可以使您的代码更多更容易调试和增强。
  6. 使用Key Bindings而不是KeyListener,因为这样您就不必使用强制焦点转移到JFrame或JPanel的方法。
  7. 尽可能尝试将视图(GUI)中的程序逻辑分离出来。创建一个或多个模型类,一个完全独立于GUI的模型类,然后围绕这些类创建GUI。这也将使您更容易增强和调试您的程序。努力使GUI尽可能 dumb ,将所有大脑留给模型。稍后您可以考虑创建一个“控制”来处理两者之间的通信。
  8. 只是玩一些代码。没有完全解决方案......

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.RenderingHints;
    import java.awt.Shape;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.KeyEvent;
    import java.awt.geom.Arc2D;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    
    import javax.swing.*;
    
    public class SimonGui {
       private static void createAndShowGui() {
          final SimonPanel simonPanel = new SimonPanel(600, 600, 1000);
    
          // create a list or random directions, just to test the GUI
          Random random = new Random();
          final List<Direction> dirList = new ArrayList<>();
          for (int i = 0; i < 15; i++) {
             int randomDirIndex = random.nextInt(Direction.values().length);
             Direction randomDir = Direction.values()[randomDirIndex];
             dirList.add(randomDir);
          }          
    
          JFrame frame = new JFrame("SimonGui");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.getContentPane().add(simonPanel);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
    
          // display the colors from the random list of directions, 
          // but wait 400 msecs to allow time for the GUI to display
          new Timer(400, new ActionListener() {
    
             @Override
             public void actionPerformed(ActionEvent e) {
                // have JPanel display the colors in the list
                simonPanel.displayDirectionList(dirList);
    
                // then stop this timer (timer should run just once)
                ((Timer) e.getSource()).stop();
             }
          }).start();
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    
    @SuppressWarnings("serial")
    class SimonPanel extends JPanel {
       private static final int GAP = 10;
       private int displayColorDelay;
       private int prefW;
       private int prefH;
       private Map<Direction, Shape> dirShapeMap = new LinkedHashMap<>();
       private Direction activeDir = null;
       private Timer displayColorTimer;
    
       public SimonPanel(int prefW, int prefH, int displayColorDelay) {
          this.prefW = prefW;
          this.prefH = prefH;
          this.displayColorDelay = displayColorDelay;
    
          int x = GAP;
          int y = GAP;
          int width = prefW - 2 * GAP;
          int height = prefH - 2 * GAP;
          int degree = 45;
          for (Direction direction : Direction.values()) {
             Shape shape = new Arc2D.Double(x, y, width, height, degree, 90, Arc2D.PIE);
             dirShapeMap.put(direction, shape);
             degree += 90;
          }
    
          setKeyBindings();
       }
    
       public void displayDirectionList(List<Direction> dirList) {
          displayColorTimer = new Timer(displayColorDelay, new DisplayColorTimerListener(dirList));
          displayColorTimer.start();
       }
    
       private void setKeyBindings() {
          Map<Direction, Integer> dirToKeyMap = new HashMap<>();
          dirToKeyMap.put(Direction.NORTH, KeyEvent.VK_UP);
          dirToKeyMap.put(Direction.WEST, KeyEvent.VK_LEFT);
          dirToKeyMap.put(Direction.SOUTH, KeyEvent.VK_DOWN);
          dirToKeyMap.put(Direction.EAST, KeyEvent.VK_RIGHT);
    
          int condition = WHEN_IN_FOCUSED_WINDOW;
          InputMap inputMap = getInputMap(condition);
          ActionMap actionMap = getActionMap();
    
          for (Direction dir : Direction.values()) {
             int keyCode = dirToKeyMap.get(dir);
             boolean keyReleased = false; // key pressed
             KeyStroke pressedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased);
             inputMap.put(pressedKeyStroke, pressedKeyStroke.toString());
             actionMap.put(pressedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased));
    
             keyReleased = true; // key released
             KeyStroke releasedKeyStroke = KeyStroke.getKeyStroke(keyCode, 0, keyReleased);
             inputMap.put(releasedKeyStroke, releasedKeyStroke.toString());
             actionMap.put(releasedKeyStroke.toString(), new KeyBindingAction(dir, keyReleased));
          }
    
       }
    
       @Override
       public Dimension getPreferredSize() {
          if (isPreferredSizeSet()) {
             return super.getPreferredSize();
          }
          return new Dimension(prefW, prefH);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
          for (Direction direction : dirShapeMap.keySet()) {
             Color color = (activeDir == direction) ? direction.getActiveColor() : direction.getPassiveColor();
             g2.setColor(color);
             g2.fill(dirShapeMap.get(direction));
          }
       }
    
       private class KeyBindingAction extends AbstractAction {
          private Direction dir;
          private boolean keyReleased;
    
          public KeyBindingAction(Direction dir, boolean keyReleased) {
             this.dir = dir;
             this.keyReleased = keyReleased;
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
             // TODO: action depending on direction and if key is pressed or released
          }
       }
    
       private class TurnOffListener implements ActionListener {
          @Override
          public void actionPerformed(ActionEvent e) {
             activeDir = null;
             repaint();
          }
       }
    
       private class DisplayColorTimerListener implements ActionListener {
          private List<Direction> directionList;
          private int counter = 0;
          private Timer turnOffTimer;
    
          public DisplayColorTimerListener(List<Direction> directionList) {
             this.directionList = directionList;
          }
    
          @Override
          public void actionPerformed(ActionEvent e) {
             Timer timer = (Timer) e.getSource();
             if (counter == directionList.size()) {
                activeDir = null;
                timer.stop();
             } else {
                activeDir = directionList.get(counter);
                counter++;
    
                // so there's a time gap in the display, so that same colors will 
                // be distinct
                int turnOffDelay = (3 * timer.getDelay()) / 4; // turn off 3/4 time into display
                turnOffTimer = new Timer(turnOffDelay, new TurnOffListener());
                turnOffTimer.setRepeats(false);
                turnOffTimer.start();
             }
             repaint();         
          }
       }
    }
    
    enum Direction {
       NORTH(Color.blue),
       WEST(Color.yellow),
       SOUTH(Color.red),
       EAST(Color.green);
    
       private Color color;
    
       private Direction(Color color) {
          this.color = color;
       }
    
       public Color getColor() {
          return color;
       }
    
       public Color getPassiveColor() {
          return color.darker();
       }
    
       public Color getActiveColor() {
          return color.brighter();
       }
    
    }