2 c j33 C_J33 于 2016.03.08 11:03 提问

repaint方法没有调用paintComponent 为啥呀

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {

public static final int B_WIDTH = 450;
public static final int B_HEIGHT = 450;
public static final int DOT_SIZE = 15;
public static final int ALL_DOTS = 900;
public static final int DELAY = 100;

private Timer timer;
boolean live = true;
Image offScreenImage = null;
Snake mySnake = new Snake();

public static void main(String[] args) {
    new Board().launchGame();
}

public void launchGame() {
    JFrame myJFrame = new JFrame();
    myJFrame.setTitle("Snake");
    myJFrame.setLocation(400,200);
    myJFrame.getContentPane().add((new Board()));
    myJFrame.pack();
    myJFrame.addKeyListener(new Board().new KeyMonitor());
    myJFrame.setVisible(true);
    myJFrame.setResizable(false);
    myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    timer = new Timer(DELAY, this);
    timer.start();
}

public Board() {
    this.setBackground(Color.BLACK);
    this.setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
    this.setFocusable(true);
    this.addKeyListener(new KeyMonitor());
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setDoubleBuffered(true);
    this.draw(g);
}

public void draw(Graphics g) {
    mySnake.draw(g);
    Food f = new Food();
    f.draw(g);
}

@Override
public void actionPerformed(ActionEvent e) {
    repaint();
}

private class KeyMonitor extends KeyAdapter {   
    @Override
    public void keyPressed(KeyEvent e) {
        mySnake.keyPressed(e);
    }
}

}

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;

public class Snake {

Board b;
Direction dir = Direction.R;
int x, y, size;
private int sX[] = new int[Board.ALL_DOTS];
private int sY[] = new int[Board.ALL_DOTS];

public Snake() {
    size = 2;
    sX[0] = 1 * Board.DOT_SIZE;
    sX[1] = 0 * Board.DOT_SIZE;
    sY[0] = 0 * Board.DOT_SIZE;
    sY[1] = 0 * Board.DOT_SIZE; 
}

public Snake(int x, int y, Board b) {
    this.x = x;
    this.y = y;
    this.b = b;
}

public void draw(Graphics g) {
    move();

    Color c = g.getColor();
    g.setColor(Color.GREEN);
    for(int i=0; i<size; i++) {
        g.fillOval(sX[i], sY[i], Board.DOT_SIZE, Board.DOT_SIZE);
    }
}

public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    switch(key) {
    case KeyEvent.VK_UP :
        if(dir == Direction.D)  break;
        dir = Direction.U; 
        break;
    case KeyEvent.VK_DOWN :
        if(dir == Direction.U)  break;
        dir = Direction.D; 
        break;
    case KeyEvent.VK_LEFT :
        if(dir == Direction.R)  break;
        dir = Direction.L; 
        break;
    case KeyEvent.VK_RIGHT :
        if(dir == Direction.L)  break;
        dir = Direction.R; 
        break;
    }
}

public void move() {
    for(int i=size-1; i>0; i--) {
        sX[i] = sX[(i-1)];
        sY[i] = sY[(i-1)];
    }

    switch(dir) {
    case U :
        sY[0] -= Board.DOT_SIZE;
        break;
    case D :
        sY[0] += Board.DOT_SIZE;
        break;
    case L :
        sX[0] -= Board.DOT_SIZE;
        break;
    case R :
        sX[0] += Board.DOT_SIZE;
        break;
    }
}

}

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

public class Food {

private int fX;
private int fY;
private static Random r = new Random();

public Food() {
    fX = r.nextInt(Board.B_WIDTH / Board.DOT_SIZE) * Board.DOT_SIZE;
    fY = r.nextInt(Board.B_HEIGHT / Board.DOT_SIZE) * Board.DOT_SIZE;
}

public void draw(Graphics g) {
    Color c = g.getColor();
    g.setColor(Color.RED);
    g.fillOval(fX, fY, Board.DOT_SIZE, Board.DOT_SIZE);
}

}

public enum Direction {
U, D, L, R
}

初学者写的贪吃蛇,用timer计时器,每隔一段时间调用一次repaint(),但运行起来发现,repaint是每隔一段时间被调用了,但paintComponent方法只被调用了一次(或者两次)。。求解啊这bug烦死我了

2个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.08 11:25

首先,你贴的代码也能让人纠结啊。直接贴代码就行了,干嘛要截图呢?别人看到代码也许可以拷贝过来帮你测测呢。
其次,paintComponent显示时被paint方法调用;其他时候是依据java 判断是否需要调用的。
还有可能是这Jpanel没有被放到一个JFrame中去显示而导致的,你定义的是JPanel而不是JFrame,实际应用中应该用JFrame的。

C_J33
C_J33 回复毕小宝: 哦哦忘记贴上去了= =
接近 2 年之前 回复
wojiushiwo945you
wojiushiwo945you 回复C_J33: 还差一个Direction类的定义。
接近 2 年之前 回复
C_J33
C_J33 我在launchGame里定义了一个jframe了 并且把jpanel add进去了呀
接近 2 年之前 回复
wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.08 14:32

是这行代码的问题:myJFrame.getContentPane().add((new Board()));
这里你本来是new Board().launchGame();结果你添加到JFrame中的却是一个新new的Border对象。
等于说你创建了两个Border对象,事件是添加在第一个Border对象上的,而在界面上的却是第二个对象。修正这行代码如下:

 myJFrame.getContentPane().add(this);

直接把当前这个Border对象添加到JFrame上OK。

wojiushiwo945you
wojiushiwo945you 回复C_J33: 那就结贴采纳呗。后续有问题继续发帖。
接近 2 年之前 回复
C_J33
C_J33 谢谢谢谢谢谢!!!!
接近 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!