重绘图形问题

时间:2014-04-26 01:50:17

标签: java swing graphics keylistener

我一直在尝试编写一个小型的侧卷轴游戏,但遇到了重绘()没有重新绘制的问题。键侦听器本身可以工作,它在按下方向键时递增和递减x和y值。只是重绘()似乎没有重新粉刷。

public class SideScroller extends JPanel implements KeyListener{
private Random random = new Random();
private int r,g,b;
private int x = 0, y = 0;

public void keyPressed(KeyEvent e) {
    if(e.getKeyCode() == e.VK_UP) {
        y -= 5;
    } else if(e.getKeyCode() == e.VK_DOWN) {
        y += 5;
    } else if(e.getKeyCode() == e.VK_LEFT) {
        x -= 5;
    } else if(e.getKeyCode() == e.VK_RIGHT) {
        x += 5;
    }
    repaint();
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}

public void paint(Graphics gg) {
    gg.setColor(new Color(r, g, b));
    gg.fillRect (x, y, 50, 50);
}

public static void main(String[] args) {
    SideScroller ss = new SideScroller();
    JFrame f = new JFrame();

    f.add(new SideScroller());
    f.setSize(500, 500);
    f.setLocationRelativeTo(null);
    f.setResizable(false);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
    f.addKeyListener(new SideScroller());
}

4 个答案:

答案 0 :(得分:1)

  • 您应该覆盖paintComponent并致电super.paintComponent,而不是paint

    protected void paintComponent(Graphics gg) {
        super.paintComponent(gg);
        gg.setColor(new Color(r, g, b));
        gg.fillRect (x, y, 50, 50);
    }
    
  • 此外,我建议您使用Key Bindings代替KeyListener

  • 此外,您应该在Event Dispacth线程上运行Swing应用程序您可以将代码包装在main

  • 中的SwingUtilities.invokeLater(...)中。

以下是上面提到的所有修复

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class SideScroller extends JPanel {

    private Random random = new Random();
    private int r, g, b;
    private int x = 0, y = 0;

    public SideScroller() {
        InputMap im = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap am = getActionMap();
        im.put(KeyStroke.getKeyStroke("UP"), "upaction");
        am.put("upaction", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                y -= 5;

                repaint();
            }
        });
        im.put(KeyStroke.getKeyStroke("DOWN"), "downaction");
        am.put("downaction", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                y += 5;
                repaint();
            }
        });
        im.put(KeyStroke.getKeyStroke("LEFT"), "leftaction");
        am.put("leftaction", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                x -= 5;
                repaint();
            }
        });
        im.put(KeyStroke.getKeyStroke("RIGHT"), "rightaction");
        am.put("rightaction", new AbstractAction() {
            public void actionPerformed(ActionEvent e) {
                x += 5;
                repaint();
            }
        });
    }

    protected void paintComponent(Graphics gg) {
        super.paintComponent(gg);

        gg.setColor(new Color(r, g, b));
        gg.fillRect(x, y, 50, 50);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JFrame f = new JFrame();

                f.add(new SideScroller());
                f.setSize(500, 500);
                f.setLocationRelativeTo(null);
                f.setResizable(false);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setVisible(true);
            }
        });
    }
}

答案 1 :(得分:1)

对于原始海报和Boann:使用Swing Timer示例进行键绑定:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;

public class GamePanel extends JPanel {
   private static final int ANIMATION_DELAY = 15;
   private final int HEIGHT = 400;
   private final int WIDTH = 600;
   private Square square;
   private EnumMap<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
   private Map<Integer, Direction> keyToDir = new HashMap<>();
   private Timer animationTimer;

   public GamePanel() {
      for (Direction dir : Direction.values()) {
         dirMap.put(dir, Boolean.FALSE);
      }
      keyToDir.put(KeyEvent.VK_UP, Direction.UP);
      keyToDir.put(KeyEvent.VK_DOWN, Direction.DOWN);
      keyToDir.put(KeyEvent.VK_LEFT, Direction.LEFT);
      keyToDir.put(KeyEvent.VK_RIGHT, Direction.RIGHT);
      setKeyBindings();
      setBackground(Color.white);
      setPreferredSize(new Dimension(WIDTH, HEIGHT));
      setFocusable(true);
      square = new Square();
      animationTimer = new Timer(ANIMATION_DELAY, new AnimationListener());
      animationTimer.start();
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      final InputMap inputMap = getInputMap(condition);
      final ActionMap actionMap = getActionMap();
      boolean[] keyPressed = { true, false };
      for (Integer keyCode : keyToDir.keySet()) {
         Direction dir = keyToDir.get(keyCode);
         for (boolean onKeyPress : keyPressed) {
            boolean onKeyRelease = !onKeyPress;
            KeyStroke keyStroke = KeyStroke.getKeyStroke(keyCode, 0,
                  onKeyRelease);
            Object key = keyStroke.toString();
            inputMap.put(keyStroke, key);
            actionMap.put(key, new KeyBindingsAction(dir, onKeyPress));
         }
      }
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      square.display(g);
   }

   private class AnimationListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent evt) {
         boolean repaint = false;
         for (Direction dir : Direction.values()) {
            if (dirMap.get(dir)) {
               square.move(dir);
               repaint = true;
            }
         }
         if (repaint) {
            repaint();
         }
      }
   }

   private class KeyBindingsAction extends AbstractAction {
      private Direction dir;
      boolean pressed;

      public KeyBindingsAction(Direction dir, boolean pressed) {
         this.dir = dir;
         this.pressed = pressed;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         dirMap.put(dir, pressed);
      }
   }

   private static void createAndShowGUI() {
      GamePanel gamePanel = new GamePanel();
      JFrame frame = new JFrame("GamePanel");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(gamePanel);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      gamePanel.requestFocusInWindow();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGUI();
         }
      });
   }
}

enum Direction {
   UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0);
   private int incrX;
   private int incrY;

   private Direction(int incrX, int incrY) {
      this.incrX = incrX;
      this.incrY = incrY;
   }

   public int getIncrX() {
      return incrX;
   }

   public int getIncrY() {
      return incrY;
   }
}

class Square {
   private int x = 0;
   private int y = 0;
   private int w = 20;
   private int h = w;
   private int step = 1;
   private Color color = Color.red;
   private Color fillColor = new Color(255, 150, 150);
   private Stroke stroke = new BasicStroke(3f, BasicStroke.CAP_ROUND,
         BasicStroke.JOIN_ROUND);

   public void display(Graphics g) {
      Graphics2D g2d = (Graphics2D) g.create();
      g2d.setColor(fillColor);
      g2d.fillRect(x, y, w, h);
      g2d.setStroke(stroke);
      g2d.setColor(color);
      g2d.drawRect(x, y, w, h);
      g2d.dispose();
   }

   public void setStep(int step) {
      this.step = step;
   }

   public void move(Direction dir) {
      x += step * dir.getIncrX();
      y += step * dir.getIncrY();
   }
}

答案 2 :(得分:0)

这里的问题是两件事。您正在将键侦听器添加到 SideScroller - 与您渲染的不同,并且您不会覆盖正确的绘制方法。

我建议您将addKeyListener(this);添加到SideScroller的构造函数中并删除f.addKeyListener(new SideScroller());,测试即被调用然后测试应该为paintComponent(Graphics g)的绘制方法。

我希望你明白如何做到这一点,以及为什么要识别密钥,但不是&#39;渲染,我不相信为初学者提供代码是个好主意。

答案 3 :(得分:0)

您正在创建三个不同的SideScroller对象。一个未使用的,第二个,您添加到框架并显示,第三个,您只用作KeyListener(调用repaint()方法)。您放入ss变量的SideScroller也应该添加到框架中并用作KeyListener。