颜色类不改变颜色

iii*_*iii 2 java user-interface swing

我正在做一个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));

}
}
Run Code Online (Sandbox Code Playgroud)

Hov*_*els 5

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

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

只是玩一些代码.没有完全解决方案的地方......

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

}
Run Code Online (Sandbox Code Playgroud)