JPanel不会重新粉刷

时间:2015-04-05 22:20:14

标签: java swing jpanel

我正在使用多个BufferedImages。我正在使用的JPanel的绘制功能在JPanel上绘制currentImg:

@Override
public void paint(Graphics g) {
    g.drawImage(currentImg, 0, 0, null);
}

使用currentImg以便我可以轻松切换图像,它在开头等于normalImg。 redImg是一个看起来与normalImg不同的BufferedImage。 现在我想画redImg半秒,然后再画一次normalImg。

currentImg = redImg;
repaint();
Thread.sleep(1000);
currentImg = normalImg;
repaint();

但是这段代码什么也没做,JPanel没有重新粉刷。这段代码有效:

currentImg = redImg;
repaint();
JOptionPane.showMessageDialog(this,"test");
Thread.sleep(1000);
JOptionPane.showMessageDialog(this,"test");
currentImg = normalImg;
repaint();

但是我不想显示消息对话框只是为了正确地重新绘制它。 感谢您的帮助:)

2 个答案:

答案 0 :(得分:5)

  1. 避免覆盖paint,尤其是顶级容器,使用基于JComponent的组件并覆盖其paintComponent方法。请查看Painting in AWT and SwingPerforming Custom Painting,了解有关在Swing气喘吁吁的更多详情
  2. 始终使用覆盖的方法调用super.paintXxx
  3. 不要在事件调度线程的上下文中使用Thread.sleep,这将阻止它处理来自EventQueue的新事件,包括重绘事件。
  4. 不要在事件调度线程的上下文之外修改UI。
  5. 请查看Concurrency in Swing以获取更多详细信息,并How to use Swing Timers查看可能的解决方案

    example

答案 1 :(得分:4)

您可以通过在paint方法和Swing事件线程中调用Thread.sleep(...)来冻结整个应用程序。不要这样做。而是使用Swing Timer并在Timer中交换JLabel的图标。

例如:

enter image description here

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.*;

public class SwapImages extends JPanel {
   private static final int TIMER_DELAY = 200;
   private static final String SPRITE_PATH = "http://th02.deviantart.net/"
         + "fs70/PRE/i/2011/169/0/8/blue_player_sprite_sheet_by_resetado-d3j7zba.png";
   public static final int SPRITE_ROWS = 6;
   public static final int SPRITE_COLS = 6;
   public static final int SPRITE_CELLS = 35;

   private JLabel label = new JLabel();
   private List<ImageIcon> iconList = new ArrayList<ImageIcon>();
   private int iconIndex = 0;

   public SwapImages() throws IOException {
      URL imgUrl = new URL(SPRITE_PATH);
      BufferedImage mainImage = ImageIO.read(imgUrl);

      for (int i = 0; i < SPRITE_CELLS; i++) {
         int row = i / SPRITE_COLS;
         int col = i % SPRITE_COLS;
         int x = (int) (((double) mainImage.getWidth() * col) / SPRITE_COLS);
         int y = (int) ((double) (mainImage.getHeight() * row) / SPRITE_ROWS);
         int w = (int) ((double) mainImage.getWidth() / SPRITE_COLS);
         int h = (int) ((double) mainImage.getHeight() / SPRITE_ROWS);
         BufferedImage img = mainImage.getSubimage(x, y, w, h);
         ImageIcon icon = new ImageIcon(img);
         iconList.add(icon);
      }
      add(label);
      label.setIcon(iconList.get(iconIndex));
      new Timer(TIMER_DELAY, new TimerListener()).start();
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent arg0) {
         iconIndex++;
         iconIndex %= iconList.size();
         label.setIcon(iconList.get(iconIndex));
      }
   }

   private static void createAndShowGui() {
      SwapImages mainPanel = null;
      try {
         mainPanel = new SwapImages();
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(-1);
      }

      JFrame frame = new JFrame("SwapImages");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}