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币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
调用repaint()后为什么这个paintComponent()没有执行
其实,这个问题很简单,很容易被忽视 100%因为你的这Jpanel没有被放到一个JFrame中去显示而导致的。还在等什么,赶快ADD上。
Java 关于paintComponent与paint有什么区别?各自的特征
重点: 1 - paint() 中调用 paintComponent(), paintBorder(), paintChildren() 2 - 最重要的区别是“双缓冲”。Swing 组件的 paint() 中实现了双缓冲,所以不要随便去覆写,会破坏双缓冲的,————建议的方式是覆写 paintComponent(),很多人做的小程序会”闪烁“,就是因为他们覆写了 paint() 方法
关于awt/swing组件中paint, update, paintComponent, repaint的经验
1、Applet/JApplet:  repaint+paint       -- dragged, paint repaint+update+paint  -- dragged, update  Applet:  repaint+paint -- 自动重画    repaint+update --  不自动重画  JApplet:都不自动重画  结论:awt组件中的paint方法自动重画
java paintComponent的一些解读
首先,paintComponent()是swing的一个方法,相当于图形版的main(),是会自执行的。如果一个class中有构造函数,则执行顺序是先执行构造函数,再执行这个。 下面直接转载一个网友关于paintComponent()的介绍: (我们明天就开始java游戏设计之旅啦!) 下面看看Swing中paint与paintComponent的区别。 查API文
java新手,用repaint方法重新绘图
最近在学习paint方法的使用,想着用一个按钮来改变背景图片(就像我们平时做的那样),然后各方查资料。当然,资料是查不到多少的,因为百度首页的前几页的那几个博客,除了一个原创之外(虽然写的很晦涩难懂),其他的都是滥竽充数之徒!最让我恼火的是百度知道里面的登徒子,一个个为了点点积分而胡乱回答,真不知道那几位问问题的同路那个时候想法。     所以我决定把我自己的repaint代码贴上,因为我冥思苦
repaint方法使用和说明
repaint 重绘此组件。如果组件是轻量组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。 目录 1方法 2工作原理 1方法编辑 repaint()方法用于重绘组件,该方法有下面四种形式: 1。public void repaint() 2。p
关于paintComponent的小细节(Graphics 类)
题目:编写一个程序,使用箭头键绘制线段。 对于这个
paint().paintComponent()方法的区别
1 - paint() 中调用 paintComponent(), paintBorder(), paintChildren() 2 - 最重要的区别是“双缓冲”。Swing 组件的 paint() 中实现了双缓冲,所以不要随便去覆写,会破坏双缓冲的,————建议的方式是覆写 paintComponent(),很多人做的小程序会”闪烁“,就是因为他们覆写了 paint() 方法,破坏了Swing
对于用到repaint带来问题的解决方案
先简单描述一下我遇到的问题;        做一个汉字部件系统要求把整张表的内容查找显示出来,而我的内容就用g.drawstring()来绘制的,需调用repaint()方法来清除上一次显示的内容,我当时想的是用一个for循环来搞定就行了,每次g.drawstring()之前先repaint(),但是想想总是美好的,发现很坑要不就是内容闪现一下不见了要不就是循环显示内容全部重叠在一起,想要改之前
paint()方法与paintComponent()方法的区别
awt控件中是在paint方法进行绘制,     所以在awt控件继承时,只要简单的覆盖paint方法就可以了。     而在swing控件中,paint方法会依次调用paintcomponent,   paintborder,   paintchildren三个方法,后两者一般默认即可,所以swing编程时,如果继承jcomponent或者其子类,要覆盖paintcomponent而不是pain