【问题标题】:What is happening with JPanel in java? What am I doing wrong?java中的JPanel发生了什么?我究竟做错了什么?
【发布时间】:2012-02-14 16:23:19
【问题描述】:

我的 JPanel 出现问题。我告诉它最后 repaint() 的构造函数,然后我有动画(一个精灵在 屏幕),但 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) {}
}

【问题讨论】:

    标签: java swing concurrency jpanel paintcomponent


    【解决方案1】:
    What am I doing wrong? 
    

    1) 使用KeyBindings 而不是KeyListener

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

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

    4) 您可以在JLabel 中使用IconJPanel 中显示BufferedImage

    【讨论】:

      【解决方案2】:

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

      两种选择:

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

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

      确保如果您在两个线程之间共享变量,则使用 volatilesynchronized(取决于您的工作方式,一个应该更适合您的需求)

      【讨论】:

        【解决方案3】:

        据我所知,您的问题是您在构造函数中调用了 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. 战斗已经画好了

        要解决您的问题,您必须在构造函数中删除对 advance() 的调用,并在显示框架后调用它。

        【讨论】:

          猜你喜欢
          • 2013-08-06
          • 1970-01-01
          • 2016-07-18
          • 1970-01-01
          • 1970-01-01
          • 2019-12-23
          • 2016-06-11
          • 1970-01-01
          • 2014-06-15
          相关资源
          最近更新 更多