Перекрасить JPanel - PullRequest
       16

Перекрасить JPanel

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

Я хотел бы перекрасить мою jPanel У меня есть класс App, который обрабатывает отображение экрана в этом JFrame. Я добавляю объект Board JPanel, который обрабатывает все JPanel. В классе совета я имел

ex = new Explosion(10, 10); 
new Thread(ex).start();

И в моем классе Explosion у меня есть конструктор, который обрезает мой файл спрайта, перезаписывает paint () и:

public void run()
    {
        while(cursor < (rows*cols))
        {
            repaint();

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(cursor);

            cursor++;
        }
    }

Цикл работает нормально, но у меня нет перерисовки на экране, отображается только первое изображение.

Что я могу сделать, чтобы обновить?

Спасибо

Редактировать: Вот мой код:

public class Explosion extends JPanel implements Runnable{

private BufferedImage img;

final int width = 320;
final int height = 320;
final int rows = 5;
final int cols = 5;

private int x,y;

private int cursor;

BufferedImage[] sprites = new BufferedImage[rows * cols];

public Explosion(int x, int y)
{
    this.x = x;
    this.y = y;

    try {
        try {
            this.img = ImageIO.read(new File((this.getClass().getResource("files/explosion2.png")).toURI()));
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    cursor = 0;

    for (int i = 0; i < rows; i++)
    {
        for (int j = 0; j < cols; j++)
        {
            sprites[(i * cols) + j] = img.getSubimage(
                i * (width/rows),
                j * (height/cols),
                width/rows,
                height/cols
            );
        }
    }
}

public void run()
{
    ActionListener taskPerformer = new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
              cursor++;
              repaint();
          }
      };

    while(cursor < (rows*cols))
    {           
          new Timer(50, taskPerformer).start();


        if (cursor==(rows*cols)-1)
            cursor=0;
    }
}

public void paintComponent(Graphics g){
    System.out.println("paintComponent");
    Graphics2D g2d = (Graphics2D)g;
    g2d.drawImage(sprites[cursor], x, y, this);
    g.dispose();    
}

/*public void paint(Graphics g) {
        super.paint(g);

        System.out.println("paint");

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawImage(sprites[cursor], x, y, this);
        Toolkit.getDefaultToolkit().sync();
        g.dispose();        
}*/


}
public class Main extends JFrame{

    public Main() 
    {
        Board board = new Board();
        add(board);
        setTitle("Explosion");
        setSize(500, 500);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);  
    }

    public static void main(String[] args) {
        new Main();
    }

}
public class Board extends JPanel{

    Explosion ex;

    public Board() 
    {           
        setDoubleBuffered(true); 

        ex = new Explosion(10,10);
        new Thread(ex).start();
    }

    public void paint(Graphics g) {
        ex.paintComponent(g);

        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }
}

Ответы [ 3 ]

3 голосов
/ 01 февраля 2012

@ StanislavL (я пока не могу комментировать): Нет, вам не нужно вызывать repaint() в EDT:

Следующие методы JComponent безопасны для вызоваиз любого потока: repaint(), revalidate() и invalidate().Методы repaint() и revalidate() ставят в очередь запросы для потока диспетчеризации событий для вызова paint() и validate() соответственно.Метод invalidate() просто помечает компонент и всех его прямых предков как требующие проверки.

Источник: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html#exceptions

cursor объявлен как volatile?В противном случае EDT может не увидеть изменения, внесенные в нить на cursor.Поэтому всегда первое изображение закрашивается.

2 голосов
/ 01 февраля 2012
  1. Не переопределяйте paint, вместо этого переопределяйте paintComponent
  2. Не используйте Thread.sleep, вместо этого используйте служебный класс, такой как javax.swing.Timer для выполненияконкретное действие в указанный интервал.Это обеспечит выполнение всех изменений в EDT и ожидание в фоновом потоке.

Обратите внимание, что без компилируемого кода трудно сказать, в чем проблема real является;это все догадки.

1 голос
/ 01 февраля 2012

Repaint должен вызываться в EDT.

Используйте SwingUtilities.invokeAndWait () или invokeLater () для вызова repaint.

...