JPanel在java中发生了什么?我究竟做错了什么?

时间:2012-02-14 16:23:19

标签: java swing concurrency jpanel paintcomponent

我的JPanel出了问题。我告诉它最后重绘() 构造函数,然后我有动画(一个精灵移动 屏幕),但JPanel在精灵消失之前不会自行绘制 通过它的动画,并在屏幕上达到了新的一点。我贴了 我的代码如下。我之前从未使用过JPanel来制作自定义图形。 我究竟做错了什么?

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;

class Battle extends JPanel implements KeyListener {

    AllyParty ap;
    boolean showMenu = false;
    BufferedImage image;
    EnemyParty ep;
    Graphics screen;
    Image allyPic[], enemyPic[];
    int enemyCount;
    int mtCount = 0;
    int turn[];
    MediaTracker mt;
    Random rand;

    public Battle(AllyParty allyparty) {

        /*Initial JPanel subclass setup*/
        setSize(800, 600);
        setBackground(Color.black);

        /*Create our ally party*/
        ap = new AllyParty();
        ap = allyparty;
        ap.setCallingObject(this);

        /*Create randomizer and random number variable*/
        long seed = System.currentTimeMillis();
        rand = new Random(seed);

        /*Use rand to select a number of enemies*/
        enemyCount = rand.nextInt(12) + 1;

        enemyCount = 12; //TEMP 
        ep = new EnemyParty(enemyCount);


        /*Create the individual enemies in ep and place them*/
        for (int i = 0; i < enemyCount; i++) {
            ep.enemy[i] = new Enemy(1);
        }

        ep.setCallingObject(this);

        /*Initialize images and set them to their starting values*/
        allyPic = new Image[4];
        enemyPic = new Image[enemyCount];

        /* for (int i = 0; i < 4; i++) 
        { 
        ap.ally[i].setCurrentImage(Ally.STAND) 
        allyPic[i] = ap.ally[i].getCurrentImage(); 
        } 

        for (int i = 0; i < enemyCount; i++) 
        { 
        enemyPic[i] = ep.enemy[i].getImage(); 
         */
        /*Set battle placement*/
        ap.setPos(0);
        ep.setPos(0);

        //Create the Buffered Image 
        image = new BufferedImage(800, 600, BufferedImage.TYPE_INT_RGB);

        //Set up the Media Tracker 
        mt = new MediaTracker(this);
        for (int i = 0; i < 4; i++) {
            mt.addImage(allyPic[i], mtCount++);
        }

        for (int i = 0; i < ep.getEnemyCount(); i++) {
            mt.addImage(enemyPic[i], mtCount++);
        }

        mt.addImage(image, mtCount++);

        try {
            mt.waitForAll();
        } catch (Exception e) {
        }

        /*Temporary Section*/
        findTurns();

        repaint();
        // ap.ally[0].advance(); 
        advance();
    }

    public void findTurns() {
        int total = ep.getEnemyCount() + 4; //Enemies + allies 

        int used[] = new int[total];
        turn = new int[total];

        int next = rand.nextInt(total);

        for (int j = 0; j < total; j++) {
            used[j] = -1;
        }

        for (int j = 0; j < total; j++) {
            for (int k = 0; k < j; k++) {
                if (used[k] == next) {
                    k = -1;
                    next = rand.nextInt(total);
                }
            }
            turn[j] = next;
            used[j] = next;
        }
    }

    public void advance() {
        while (ap.ally[0].getXPos() > 350) {
            ap.ally[0].moveLeft(20);
            ap.ally[0].setCurrentImage(Ally.WALK);
            repaint();
            try {
                Thread.sleep(200);
            } catch (Exception e) {
            }
            ap.ally[0].setCurrentImage(Ally.STAND);
            repaint();
            try {
                Thread.sleep(200);
            } catch (Exception e) {
            }
        }
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        screen = image.getGraphics();

        for (int i = 0; i < 4; i++) {
            allyPic[i] = ap.ally[i].getCurrentImage();
        }

        for (int i = 0; i < ep.getEnemyCount(); i++) {
            enemyPic[i] = ep.enemy[i].getCurrentImage();
        }

        for (int i = 0; i < 4; i++) {
            screen.drawImage(allyPic[i], ap.ally[i].getXPos(),
                ap.ally[i].getYPos(), this);
        }

        for (int i = 0; i < enemyCount; i++) {
            screen.drawImage(enemyPic[i], ep.enemy[i].getXPos(),
                ep.enemy[i].getYPos(), 100, 75, this);
        }

        g.drawImage(image, 0, 0, this);
    }

    public void keyPressed(KeyEvent k) {}
    public void keyReleased(KeyEvent k) {}
    public void keyTyped(KeyEvent k) {}
}

3 个答案:

答案 0 :(得分:6)

What am I doing wrong? 

1)使用KeyBindings代替KeyListener

2)在EDT期间永远不要使用Thread.sleep(int),因为导致freeze Swing GUI

3)动画/延迟事件使用Swing Timer

4)您可以使用Icon中的JLabelJPanel

中显示BufferedImage

答案 1 :(得分:4)

你可能会在AWT-Thread中修改你的“模型”(精灵的位置)。重绘是在AWT-EventThread中调度的事件。因此,只要您的操作在AWT-Thread内部运行,您就会阻止重新绘制面板的AWT。

两个选项:

1)将“操作/模型”移到AWT-Thread之外(在不同的线程中)

2)不时释放AWT-Thread,允许执行重绘事件(对我来说这不是一个好选择)

请确保如果您在两个主题之间共享变量,则使用volatilesynchronized(取决于您的工作方式,最适合您的需求)

答案 2 :(得分:0)

据我所知,你的问题是你在构造函数中调用advance()。 您的代码看起来可能是这样的:

JFrame frame = new JFrame();
frame.add(new Battle());
frame.setVisible(true);

以下是发生的事情:

  1. 创建了一个新的JFrame
  2. 创建了新的战斗
  3. 在Battle构造函数结束时,repaint()被称为
  4. 然后调用advance()
  5. advance()本身多次调用重绘
  6. advance()返回
  7. 构造函数返回
  8. 战斗被添加到框架
  9. 框架可见
  10. 战斗被涂上
  11. 要解决您的问题,您必须在构造函数中删除对advance()的调用,并在显示框架后调用它。