Что происходит с JPanel в Java? Что я делаю неправильно? - PullRequest
1 голос
/ 14 февраля 2012

У меня проблема с моей 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) {}
}

Ответы [ 3 ]

6 голосов
/ 14 февраля 2012
What am I doing wrong? 

1) использовать KeyBindings вместо KeyListener

2) никогда не использовать Thread.sleep(int) во время EDT, потому что заморозить Swing GUI

3) для анимации / использования события с задержкой Swing Timer

4) вы можете использовать Icon в JLabel для отображения BufferedImage в JPanel

4 голосов
/ 14 февраля 2012

По всей вероятности, вы изменяете свою "модель" (позицию вашего спрайта) в AWT-Thread. Перекрасить - это события, отправленные в AWT-EventThread. Поэтому вы блокируете AWT для перекрашивания панели, пока ваши операции выполняются в AWT-Thread.

Два варианта:

1) Переместите ваши «операции / модель» за пределы AWT-нити (в другой ветке)

2) Время от времени выпускайте AWT-Thread, позволяя выполнять события перерисовки (для меня это не очень хороший вариант)

Убедитесь, что если вы разделяете переменные между двумя потоками, которые вы используете volatile или synchronized (в зависимости от того, как вы работаете, лучше подойдет вашим потребностям)

0 голосов
/ 14 февраля 2012

Насколько я могу судить, ваша проблема в том, что вы вызываете advance () в конструкторе. Ваш код выглядит примерно так:

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

Вот что происходит:

  1. создан новый JFrame
  2. создана новая битва
  3. в конце битвы конструктор repaint () называется
  4. тогда advance () называется
  5. advance () сам вызывает перерисовку несколько раз
  6. advance () возвращает
  7. конструктор возвращает
  8. Битва добавлена ​​в кадр
  9. рамка сделана видимой
  10. Битва расписана

Чтобы решить вашу проблему, вы должны удалить вызов метода advance () в конструкторе и вызывать его после показа вашего фрейма.

...